您的位置:首页 > 其它

POJ1965 The Pilots Brothers' refrigerator(dfs,回溯,枚举)

2017-09-08 21:30 309 查看
POJ2965

题意分析:

有个4*4的0/1图,初始状况是随机的。每次可以选16个位置中的一个位置翻,每翻一次,该位置所在的行和列的所有值都被取反,问要至少翻几次才能把它翻成全是减号。

和POJ1753类似,这里用的dfs+回溯法写的,先把格子转换成0/1图,然后dfs即可。

这道题应该还可以用类似POJ1753的状压,写出变换数组T[i],每次对应位置的变形就相当于是该图的十进制进行异或变换,一共有16种变形,后来补吧。

dfs+回溯:

#include<iostream>
#include<math.h>
#include<algorithm>
using namespace std;
int x[20],y[20]; //临时路径
int ansX[20],ansY[20]; //最终路径
int ans=33;  //最多翻转33次

int mp[5][5];
void init(){
char ch;
for(int i=0;i<4;i++){
for(int j=0;j<4;j++){
cin>>ch;
if(ch=='-') mp[i][j]=1;
else mp[i][j]=0;
}
}
}

bool complete(){
for(int i=0;i<4;i++){
for(int j=0;j<4;j++){
if(mp[i][j]==0) return false;
}
}
return true;
}
void flip(int s){
int x1=s/4;
int y1=s%4;
for(int i=0;i<4;i++){
mp[i][y1]=!mp[i][y1];
mp[x1][i]=!mp[x1][i];
}
mp[x1][y1]= !mp[x1][y1];
}
void dfs(int s,int b){  //s代表当前处理的格子,b代表翻转格子次数
if(complete()){
if(ans>b){ //最多翻转an=33次
ans=b;
for(int i=1;i<=ans;i++){
ansX[i]=x[i];
ansY[i]=y[i];
}
return ;
}
}
if(s>=16) return ;
dfs(s+1,b); //不管第s个格子,直接向下找

flip(s);  //翻转第s个格子
x[b+1]=s/4+1;  //临时路径
y[b+1]=s%4+1;
dfs(s+1,b+1);
flip(s); //回溯
}

int main(){
init();
dfs(0,0);
cout<<ans<<endl;
for(int i=1;i<=ans;i++){
printf("%d %d\n",ansX[i],ansY[i]);
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: