http://poj.org/problem?id=1753
这个题目一看就要用搜索,但是如何最小? 题目只有4*4 行 ,所以好说了,暴力dfs。
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 #include<stdio.h> 2 char map[4][4]; 3 int vis[4][4]; 4 int step,flag; 5 int judge() 6 { 7 int i,j; 8 for(i=0;i<4;i++) 9 for(j=0;j<4;j++) 10 if(vis[i][j]!=vis[0][0]) 11 return 0; 12 13 return 1; 14 } 15 void turn(int i,int j) 16 { 17 vis[i][j]=!vis[i][j]; 18 if(i>0) vis[i-1][j]=!vis[i-1][j]; 19 if(i<3) vis[i+1][j]=!vis[i+1][j]; 20 if(j>0) vis[i][j-1]=!vis[i][j-1]; 21 if(j<3) vis[i][j+1]=!vis[i][j+1]; 22 } 23 void dfs(int i,int j,int step1) 24 { 25 26 if(step==step1) 27 { 28 if(judge()) 29 flag=1; 30 31 return ; 32 } 33 if(flag ||i==4) return ; 34 turn(i,j); 35 if(j<3) 36 dfs(i,j+1,step1+1); 37 else 38 dfs(i+1,0,step1+1); 39 turn(i,j); 40 if(j<3) 41 dfs(i,j+1,step1); 42 else 43 dfs(i+1,0,step1); 44 return ; 45 } 46 int main() 47 { 48 int i,j; 49 for(i=0;i<4;i++) 50 scanf("%s",map[i]); 51 for(i=0;i<4;i++) 52 { 53 for(j=0;j<4;j++) 54 { 55 if(map[i][j]=='b') 56 vis[i][j]=1; 57 else 58 vis[i][j]=0; 59 60 } 61 62 } 63 flag=0; 64 for(step=0;step<=16;step++) 65 { 66 dfs(0,0,0); 67 if(flag) 68 break; 69 } 70 if(flag) 71 printf("%d ",step); 72 else 73 printf("Impossible "); 74 return 0; 75 }
基于以上代码,我自己又写了一个,本想优化优化,结果一直wa,看了一下午加一晚上,还是没有搞清。
找啊找,找不同。先把代码放在这里,过几天再看看,说不定就找到原因了,读者能找到不同么?欢迎来踩!
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 #include<stdio.h> 2 #include<string.h> 3 char m[4][10]; 4 int s[4][4]; 5 int limit; 6 int ok=0;//是否完成反转,为一时,全部一样 7 int check() 8 { 9 for(int i=0;i<4;i++) 10 for(int k=0;k<4;k++) 11 { 12 if(s[i][k]!=s[0][0])return 0; 13 } 14 return 1;//全部一样的时候返回1,不一样的时候返回0 15 } 16 void turn(int x,int y) 17 { 18 s[x][y]=!s[x][y]; 19 if(x>=1)s[x-1][y]=!s[x-1][y]; 20 if(x<=2)s[x+1][y]=!s[x+1][y]; 21 if(y>=1)s[x][y-1]=!s[x][y-1]; 22 if(y<=2)s[x][y+1]=!s[x][y+1]; 23 } 24 void dfs(int x,int y,int step) 25 { 26 if(step==limit&&check()){ok=1;printf("%d ",limit);return;} 27 if(x<0||y<0||x>=4||y>=4||step>limit||ok) 28 { 29 return; 30 } 31 32 turn(x,y);//假设要翻开 33 if(y<=2)dfs(x,y+1,step+1); 34 else dfs(x+1,0,step+1); 35 turn(x,y);//运行到此步说明以上翻牌不行时,应该翻回去,翻其他的牌 36 if(y<=2)dfs(x,y+1,step); 37 else dfs(x+1,0,step); 38 return ; 39 } 40 41 int main() 42 { 43 for(int i=0;i<4;i++) 44 scanf("%s",m[i]); 45 for(int i=0;i<4;i++) 46 { 47 //printf("%s ",m[i]); 48 for(int k=0;k<4;k++) 49 { 50 if(m[i][k]=='b')s[i][k]=0; 51 else s[i][k]=1; 52 } 53 } 54 55 for(limit=0;limit<=16;limit++) 56 { 57 dfs(0,0,0); 58 if(ok==1)break; 59 } 60 if(ok==0)printf("Impossible "); 61 else printf("%d ",limit); 62 return 0; 63 }
无语了,原来我在函数验证时输出了一次,忘记把代码注释掉。
一段时间后,我又重写了此题,作为复习,发现新的代码更为清晰。
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
#include<cstdio> #include<cstring> #include<iostream> using namespace std; #define M 4 #define mem0(f) memset(f,0m,sizeof(f)) char s[10][10]; int map[M][M]; int ok,limit; void check() { for(int i=0;i<M;i++) for(int k=0;k<M;k++) { if(map[i][k]!=map[0][0]) { ok=0;return; } } ok=1; } void turn(int x,int y) { map[x][y]=!map[x][y]; if(x>0)map[x-1][y]=!map[x-1][y]; if(x<M-1)map[x+1][y]=!map[x+1][y]; if(y>0)map[x][y-1]=!map[x][y-1]; if(y<M-1)map[x][y+1]=!map[x][y+1]; } void dfs(int x,int y,int step) { check(); //printf("ok=%d ",ok); if(x<0||y<0||x>=M||y>=M||ok==1||step==limit)return; turn(x,y); if(x==M-1)dfs(0,y+1,step+1); else dfs(x+1,y,step+1); if(ok)return; turn(x,y); if(x==M-1)dfs(0,y+1,step); else dfs(x+1,y,step); return; } int main() { while(~scanf("%s",s[0])) { scanf("%s",s[1]); scanf("%s",s[2]); scanf("%s",s[3]); for(int i=0;i<M;i++) { for(int k=0;k<M;k++) { if(s[i][k]=='b')map[i][k]=0; else map[i][k]=1; } } ok=0; for(int i=0;i<=16;i++) { limit=i; dfs(0,0,0); if(ok){break;} } if(ok)printf("%d ",limit); else printf("Impossible "); } return 0; }
这应该也是思维提升的表现吧。好了,好好加油,看看日后有没有一个比这个暴力的方法更好的解法,毕竟搜索时这个算法重复了好多次。