1. 程式人生 > >POJ 3279 Fliptile(DFS+反轉)

POJ 3279 Fliptile(DFS+反轉)

puts 時間復雜度 有一個 坐標 pos 上下左右 clas main target

題目鏈接:http://poj.org/problem?id=3279

題目大意:有一個n*m的格子,每個格子都有黑白兩面(0表示白色,1表示黑色)。我們需要把所有的格子都反轉成黑色,每反轉一個格子,它上下左右的格子都會跟著反轉。請求出用最小步數完成反轉時每個格子反轉的次數。有多個解時,輸出字典序最小的一組。

解題思路:只要枚舉第一行的2^m種情況,如果一個位置上一行是1,那這個位置一定要反轉,因為只有這一行能改變上一行,所以每一行的狀態都是由前一行決定的。只要最後判斷最後一行是不是都是0即可,關於最小字典序,只要從右往左枚舉,第一個方案就是正解。(時間復雜度O(n*m*2^m)。

代碼:

 1
#include<cstdio> 2 #include<cstring> 3 using namespace std; 4 const int N=20; 5 6 int n,m; 7 bool flag; 8 int map[N][N],sta[N][N],tmp[N][N];//sta表示踩或不踩 9 int d[5][2]={{0,1},{1,0},{0,0},{0,-1},{-1,0}}; 10 11 12 //反轉坐標為(i,j)的格子 13 void reverse(int i,int j,int s[][N]){ 14 for
(int k=0;k<5;k++){ 15 int x=i+d[k][0]; 16 int y=j+d[k][1]; 17 s[x][y]=!s[x][y]; 18 } 19 } 20 21 void dfs(int y){ 22 if(flag) 23 return; 24 if(y>=1){ 25 //不踩 26 sta[1][y]=0; 27 dfs(y-1); 28 // 29 sta[1
][y]=1; 30 reverse(1,y,map); 31 dfs(y-1); 32 reverse(1,y,map); 33 } 34 else{ 35 for(int i=1;i<=n;i++){ 36 for(int j=1;j<=m;j++){ 37 tmp[i][j]=map[i][j]; 38 } 39 } 40 for(int i=2;i<=n;i++){ 41 for(int j=1;j<=m;j++){ 42 sta[i][j]=0; 43 if(tmp[i-1][j]==1){ 44 reverse(i,j,tmp); 45 sta[i][j]=1; 46 } 47 } 48 } 49 50 bool sign=true; 51 for(int i=1;i<=m;i++){ 52 if(tmp[n][i]==1){ 53 sign=false; 54 break; 55 } 56 } 57 if(sign){ 58 flag=true; 59 for(int i=1;i<=n;i++){ 60 for(int j=1;j<=m;j++){ 61 if(j==m) 62 printf("%d\n",sta[i][j]); 63 else 64 printf("%d ",sta[i][j]); 65 } 66 } 67 } 68 } 69 } 70 71 int main(){ 72 while(~scanf("%d%d",&n,&m)){ 73 memset(sta,0,sizeof(sta)); 74 flag=false; 75 for(int i=1;i<=n;i++){ 76 for(int j=1;j<=m;j++){ 77 scanf("%d",&map[i][j]); 78 } 79 } 80 dfs(m); 81 if(!flag) 82 puts("IMPOSSIBLE"); 83 } 84 return 0; 85 }

POJ 3279 Fliptile(DFS+反轉)