题目链接http://poj.org/problem?id=2965
此题与1753类似,同样用dfs枚举,学长学姐们应该就是想让我们先练一下这些基础吧。。
思路几乎来说都一样,不赘述了。
但是TLE了大半天,太弱了orz。。。
问题在于我用了跟1753一样的方法,将这种情况下的所有点找到才一起翻转,,这样就会出现一个问题,那么就是比如选五个点 0 1 2 3 4 5 找到后一起翻,之后选到0 1 2 3 4 6,也是找到后一起翻,,然后这样0 1 2 3 4 这几个点都重复翻,,想了一下这样导致做了很多的无用功,真该TLE。。。之前想了好久不知道怎么改,最后想到在找到点的时候就直接翻转,不要这个点的时候再翻回来。。这样就不会有那么多无用功。。比如0 1 2 3 4 每个找出来后都直接翻了,那么最后一个放5 或者6等其他的都不会再翻前面的,与之前相比大大缩短了时间。。
#include<stdio.h> #include<string.h> char s[20]; int a[20]; int visit[20],ans[20]; int flag=0; int is_win() { int i; for(i=0;i<16;i++) if(a[i]==0) return 0; return 1; } void flip(int depth) { int i,j,k,n; int x=ans[depth]/4; int y=ans[depth]%4; for(j=0;j<16;j++) if(j/4==x||j%4==y) a[j]=!a[j]; } void dfs(int depth,int start,int r) { int i,n; if(flag==1) return ; if(depth==r) { flag=is_win(); if(flag) { printf("%d\n",depth); for(i=0;i<depth;i++) printf("%d %d\n",ans[i]/4+1,ans[i]%4+1); } return ; } else for(i=start;i<=16-r+depth;i++) { if(!visit[i]) { visit[i]=1; ans[depth]=i; //保存需要翻的点 flip(depth); //选取这个位置翻转 dfs(depth+1,i+1,r); flip(depth); //将这个位置翻回来 visit[i]=0; } } } int main () { int i,j,r; flag=0; memset(visit,0,sizeof(visit)); for(i=0;i<16;i++) { char ch; ch=getchar(); if(ch=='\n') i--; else s[i]=ch; if(s[i]=='+') a[i]=0; else a[i]=1; } if(is_win()) printf("0\n"); else for(i=1;i<=16;i++) { memset(ans,0,sizeof(ans)); dfs(0,0,i); if(flag==1) break; } return 0; }
别人写的二维数组的dfs,值得我学习,确实这方面还很弱。附上链接http://blog.csdn.net/lyy289065406/article/details/6642597
下面是链接中的代码
/*代码一:DFS+Enum*/ //Memory Time //240K 641MS //本题由于要输出每次翻转的棋子,因此不适宜用BFS,应该使用DFS输出完整路径 #include<iostream> using namespace std; bool lock[10][10]={false}; bool flag; int step; int ri[16],cj[16]; bool isopen(void) { for(int i=3;i<7;i++) for(int j=3;j<7;j++) if(lock[i][j]!=true) return false; return true; } void flip(int row,int col) //其实参考POJ1753的翻棋方法也是可以做出来的,但是会超时不通过 { //超时的原因就是翻棋时有太多多余的操作 lock[row][col]=!lock[row][col]; //POJ1753使用6x6矩形,多余操作只有周围的“一圈”翻棋! for(int i=3;i<=6;i++) //这里使用10x10矩形,多余操作有“三圈”翻棋! lock[i][col]=!lock[i][col]; //其实用位运算就可以只使用4x4矩形,大大降低时间复杂度,根本没有多余操作,但是程序会很复杂,不好看 for(int j=3;j<=6;j++) lock[row][j]=!lock[row][j]; return; } void dfs(int row,int col,int deep) { if(deep==step) { flag=isopen(); return; } if(flag||row==7)return; flip(row,col); ri[deep]=row; cj[deep]=col; if(col<6) dfs(row,col+1,deep+1); else dfs(row+1,3,deep+1); flip(row,col); if(col<6) dfs(row,col+1,deep); else dfs(row+1,3,deep); return; } int main(void) { char temp; int i,j; for(i=3;i<7;i++) for(j=3;j<7;j++) { cin>>temp; if(temp=='-') lock[i][j]=true; } for(step=0;step<=16;step++) { dfs(3,3,0); if(flag)break; } cout<<step<<endl; for(i=0;i<step;i++) cout<<ri[i]-2<<' '<<cj[i]-2<<endl; return 0; }