您的位置:首页 > 其它

POJ 1753(DFS+枚举||BFS+位运算)

2016-01-23 10:26 411 查看
题目链接http://poj.org/problem?id=1753

题意:给出一个4*4方格,b表示黑棋,w表示白棋,每次选定一个棋子,将其以及相邻点翻转,需要多少次才能使棋子全为白色或者黑色?

思路:每次棋子最多只需要翻转1次(翻转偶数次和不翻转一样,翻转奇数次和翻转1次结果一样),所以最多有2^16个不同的状态,直接枚举+DFS回溯就可以判断;

另外一种思路,每个棋子的状态用二进制0或1表示,可以看成共有16个二进制数,最大为65535,可以采取位运算的方式将其翻转,用队列维护,队列中的数为0或65535(即全黑或全白)的时候,表明可以在有限次内完成,若队列最后为空,则输出Impossible。

①:DFS枚举+回溯:

#include<iostream>
#include<cstdio>
using namespace std;

const int maxn=10005;
int T,n,m;
bool chess[10][10];
int dx[]={-1,1,0,0,0};
int dy[]={0,0,0,-1,1};
int step;
bool flag=false;

bool judge(){//判断是否为全黑或全白
for(int i=1;i<=4;i++){
for(int j=1;j<=4;j++){
if(chess[i][j]!=chess[1][1])
return false;
}
}
return true;
}

void Flip(int row,int col){//翻转当前格子和相邻四个格子
for(int i=0;i<5;i++){
chess[row+dx[i]][col+dy[i]]=!chess[row+dx[i]][col+dy[i]];
}
return ;
}

void dfs(int row,int col,int deep){
if(deep==step){
flag=judge();
return ;
}
if(flag||row==5) return ;
Flip(row,col);//翻棋
if(col<4)
dfs(row,col+1,deep+1);
else
dfs(row+1,1,deep+1);

Flip(row,col);//回溯,再次翻转
if(col<4)
dfs(row,col+1,deep);
else
dfs(row+1,1,deep);
}

int main(){
#ifndef ONLINE_JUDGE
freopen("test.in","r",stdin);
freopen("test.out","w",stdout);
#endif
char ch;
for(int i=1;i<=4;i++){
for(int j=1;j<=4;j++){
cin>>ch;
if(ch=='b')
chess[i][j]=true;
else
chess[i][j]=false;
}
}
for(step=0;step<=16;step++){
dfs(1,1,0);
if(flag)
break;
}
if(flag)
printf("%d\n",step);
else
printf("Impossible\n");
}


②BFS+位运算:

<pre name="code" class="cpp">#include<iostream>
#include<cstdio>
#include<cstring>
#include<queue>
using namespace std;

const int maxn=65536;
int T,n,m;
bool vis[maxn];
int dx[]={-1,1,0,0,0};
int dy[]={0,0,0,-1,1};

int state[16]={
51200,58368,29184,12544,
35968,20032,10016,4880,
2248,1252,626,305,
140,78,39,19
};

struct node{
int number;
int step;
};

int BFS(int init){
memset(vis,false,sizeof(vis));
queue<node>q;
node s,e;
s.number=init;
s.step=0;
vis[s.number]=true;
q.push(s);
while(!q.empty()){
s=q.front();
q.pop();
if(s.number==0||s.number==0xffff)
return s.step;
for(int i=0;i<16;i++){
e.number=s.number^state[i];
e.step=s.step+1;
if(vis[e.number])
continue;
else{
vis[e.number]=true;
q.push(e);
}
}
}
return -1;
}

int main(){
char ch;
int init=0;
for(int i=1;i<=4;i++){
for(int j=1;j<=4;j++){
cin>>ch;
init<<=1;//左移一位
if(ch=='b')
init+=1;
}
}
int ans=BFS(init);
if(ans!=-1)
printf("%d\n",ans);
else
printf("Impossible\n");
}



                                            
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: