题目链接:http://acm.sdut.edu.cn/sdutoj/problem.php?action=showproblem&problemid=2410
首先对第一行进行枚举,不冲突即可,其他行:上一行为0,此行不能放雷,上一行为1,此处进行枚举,不冲突即可。而且有几个很坑的地方,我就不多说了,代码有备注,自己看吧。。。
#include<iostream> #include<cstdio> #include<cstring> using namespace std; int n,m,flag; char mine[25][25],aa[25][25]; int dx[]={0,-1,0,1,0},dy[]={0,0,-1,0,1}; int a[25][25]; bool outmap(int x,int y) { if(x<0||x>=n||y<0||y>=m) return true; return false; } void down(int x,int y) //该点是雷,周围减1 { int i,xx,yy; for(i=0;i<5;i++) { xx=x+dx[i]; yy=y+dy[i]; if(!outmap(xx,yy)) a[xx][yy]--; } } void up(int x,int y) //该点不是雷,周围加1 { int i,xx,yy; for(i=0;i<5;i++) { xx=x+dx[i]; yy=y+dy[i]; if(!outmap(xx,yy)) a[xx][yy]++; } } int check2(int x,int y) //判断周围是否符合条件 { int i,xx,yy; for(i=0;i<5;i++) { xx=x+dx[i]; yy=y+dy[i]; if(!outmap(xx,yy)) if(a[xx][yy]<=0) return 0; } return 1; } int check3() { int i; for(i=0;i<m;i++) if(a[n-1][i]!=0) return 0; return 1; } void print() { int i,j; for(i=0;i<n;i++) { for(j=0;j<m;j++) printf("%c",mine[i][j]); printf("\n"); } } void dfs(int x,int y) { if(flag) return; if(x==n) { if(check3()) { flag=1; print(); //经过,我无数次的实验,貌似print()这个输出不放在这个位置就会一直wrong。。。 //我在想会不会有没有符合情况的没有输出呀。。。 } return ; } if(y==m) { dfs(x+1,0); return; } if(x==0) // 首先对第一行进行枚举,不冲突即可 { if(check2(x,y)) { mine[x][y]='*'; down(x,y); dfs(x,y+1); up(x,y); } mine[x][y]='.'; dfs(x,y+1); } else { if( a[x-1][y]==0 ) // 上一行为0,此行不能放雷 { mine[x][y]='.'; dfs(x,y+1); } else if( a[x-1][y]==1 ) // 上一行为1,此处进行枚举,不冲突即可 if( check2(x,y) ) { mine[x][y]='*'; down(x,y); dfs(x,y+1); up(x,y); } } } int main() { int T,t=1; scanf("%d",&T); while(T--) { int i,j; flag=0; scanf("%d%d",&n,&m); for(i=0;i<n;i++) scanf("%s",aa[i]); for(i=0;i<n;i++) for(j=0;j<m;j++) a[i][j]=aa[i][j]-'0'; printf("Case %d:\n",t++); //尼玛,真不想吐槽,放在dfs(0,0)后就一直wrong... dfs(0,0); } return 0; }