您的位置:首页 > 其它

POJ 1321 棋盘问题 DFS 和 状态压缩DP

2016-09-04 15:32 344 查看
好吧,自己的状态压缩DP不是很会,所以就拿这个来练练手好了。

状态压缩很快呀,只是需要更大的内存开销,不过为了时间,也是值得的,我的代码状态压缩0ms搜索却用了47ms。嗯,这个DP要好好学一下。

原理:第二维下标表示当前的局面,1表示这个格子上是不能摆东西的。

代码:
#include<cstdio>
#include<cstring>
#include<climits>

using namespace std;

int num[UCHAR_MAX+10],limit,n,k,judge[10],arr[10][UCHAR_MAX+10],calc(int x),ans;
char c;

int main(){
for(int i=1;i<=UCHAR_MAX;++i)
num[i]=calc(i);
arr[0][0]=1;
while(scanf("%d%d%*c",&n,&k)&&n!=-1){
for(int i=1;i<=n;++i){
for(int j=0;j<n-1;++j){
scanf("%c",&c);
if(c=='.')
judge[i]|=1<<j;
}
scanf("%c%*c",&c);
if(c=='.')
judge[i]|=1<<(n-1);
}

limit=1<<n;

for(int i=1;i<=n;++i){
for(int j=0;j<limit;++j)
if(num[j]<=k){
arr[i][j]+=arr[i-1][j];
for(int t=0;t<n;++t){;
if((((1<<t)&judge[i])==0)&&(j&(1<<t))==0)
arr[i][j|(1<<t)]+=arr[i-1][j];
}
}
}

for(int i=0;i<limit;++i)
if(num[i]==k)
ans+=arr
[i];
printf("%d\n",ans);

ans=0;memset(judge,0,sizeof(judge));
for(int i=1;i<=n;++i)
memset(arr[i],0,sizeof(int)*limit);
}
return 0;
}

int calc(int x){
int times=0;
while(x){
if(x&1)
++times;
x>>=1;
}
return times;
}


注意,在写状态转移方程的时候用到了一个num[j]<=k这个实际上是可以省略的,只是会慢一些而已。

DFS水过:

#include<cstdio>

using namespace std;

int ans,board[10][10],n,k;
void dfs(int rows,int num);
bool flag[10];

int main(){
while(scanf("%d%d%*c",&n,&k)&&n!=-1){
for(int i=0;i<n;++i){
for(int j=0;j<n-1;++j)
scanf("%c",&board[i][j]);
scanf("%c%*c",&board[i][n-1]);
}

dfs(0,0);
printf("%d\n",ans);
ans=0;
}
return 0;
}

void dfs(int rows,int num){
if(num==k){
++ans;
return;
}
if(rows>=n)
return;
for(int i=0;i<n;++i){
if(board[rows][i]=='#'&&!flag[i])
flag[i]=true,dfs(rows+1,num+1),flag[i]=false;
}
dfs(rows+1,num);
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息