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

来源:互联网 发布:java中linkedlist用法 编辑:程序博客网 时间:2024/06/14 04:55

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;}
阅读全文
0 0
原创粉丝点击