BZOJ2669

来自蒟蒻XXJ的做题记录

观察一下就知道里面最多会有8个X嘛== 然后就状压一下啊……

\(f[i][j]=f[i-1][j]*(cnt[s]-i+1)+f[i-1][j-(1<<p)]\)

PS:cnt[s] 表示一个填好的状态s下有多少个地方可以放数字i

来自dalao PoPoQQQ:

原来只考虑了保证标记的位置都是局部最小值

但是问题是这样虽然保证了标记的位置都是局部最小值,但是可能会导致一些未标记的位置成为局部极小值,因此我们枚举其他可以成为局部极小值的位置,容斥一下即可

所以正解是枚举每一种可能的局部最小值分布,用状压dp求出方案数,然后容斥(一步减,两步加)

#include<bits/stdc++.h>
using namespace std;
const int MOD=12345678;
int n,m,x[9],y[9],top,cnt[1<<9];
long long f[30][1<<9];
long long ans;
bool mm[6][9],wtm[6][9];
int dx[]={0,1,0,-1,1,-1,1,-1};
int dy[]={1,0,-1,0,1,-1,-1,1};
int dp(){
	top=0;int s;memset(cnt,0,sizeof(cnt));
	memset(f,0,sizeof(f));
	for(int i=0;i<n;i++)
		for(int j=0;j<m;j++)
			if(mm[i][j]){
				x[++top]=i;y[top]=j;
			}
	s=1<<top;
	for(int i=0;i<s;i++){
		memset(wtm,0,sizeof(wtm));
		for(int j=0;j<top;j++){
			if(!((1<<j)&i)){
				for(int k=0;k<8;k++){
					int xx=x[j+1]+dx[k];
					int yy=y[j+1]+dy[k];
					if(xx<0||yy<0||xx>=n||yy>=m) continue;
					wtm[xx][yy]=1;
				}
				wtm[x[j+1]][y[j+1]]=1;
			}
		}
		for(int ni=0;ni<n;ni++)
			for(int nj=0;nj<m;nj++) cnt[i]+=!(wtm[ni][nj]);
	}
 	f[0][0]=1;
	for(int i=1;i<=n*m;i++)
		for(int j=0;j<s;j++){
			f[i][j]+=(f[i-1][j]*(cnt[j]-i+1))%MOD;
			f[i][j]%=MOD;
			for(int p=0;p<top;p++){
				if(!((1<<p)&j)) continue;
				f[i][j]+=f[i-1][j-(1<<p)];
				f[i][j]%=MOD;
			}
		}
	return f[n*m][s-1];
}
void dfs(int nx,int ny,int z){
	if(ny==m){dfs(nx+1,0,z);return;}
	if(nx==n){
		ans+=dp()*z;
		ans%=MOD;
		return;
	}//Judge that the spot can be X or not Just Judge its round
	dfs(nx,ny+1,z);
	int judge(1);
	for(int i=0;i<8;i++){
		int xx=nx+dx[i];
		int yy=ny+dy[i];
		if(xx<0||yy<0||xx>=n||yy>=m) continue;
		if(mm[xx][yy]) {judge=0;break;}
	}
	if(mm[nx][ny]) judge=0;
	if(judge){mm[nx][ny]=1;dfs(nx,ny+1,z*(-1));mm[nx][ny]=0;}
}
void input(){
	cin>>n>>m;
	cin.get();
	for(int i=0;i<n;i++){
		char c[10];
		scanf("%s",c);
		for(int j=0;j<m;j++){
			if(c[j]=='X') mm[i][j]=1;
			else mm[i][j]=0;
		}
	}
}
void xxj(){
	dfs(0,0,1);
}
void output(){
	cout<<(ans+12*MOD)%MOD<<endl;
}

int main(){
	input();
	xxj();
	output();
	return 0;
}
posted @ 2017-03-23 11:20  Xiaojian_xiang  阅读(372)  评论(0编辑  收藏  举报