http://www.sdutacm.org/sdutoj/problem.php?action=showproblem&problemid=2410
只要是第一行确定了,全部棋局也就确定了,dfs搜索第一行的情况,然后后面的直接根据上一行而定,这样最后就能得出整个矩阵了,第一行最多20个,也就是复杂度为2^20,不会超时,并且中间还会有剪枝。
但是苦逼的是当时模拟的时候感觉dfs没什么用,只要第一行确定了其他就能确定的话,我直接二进制分解获得第一行就行了,但是这样做了好久,却不是TL就是WR,至今不知道为何,以后有时间了再看吧。。。(顺便也贴下第一次二进制分解的错误方法。。)
#include <iostream> #include <cstdio> #include <string> #include <cstring> #define MAX 500 using namespace std; char ch[100][100],res[100][100]; int T,n,m; int dir[][2]= {{-1,0},{1,0},{0,-1},{0,1},{0,0}}; int mark=0; bool OK(int x,int y){ int tempx,tempy; for(int i=0;i<5;i++){ tempx=x+dir[i][0],tempy=y+dir[i][1]; if( (tempx<0 || tempx>=n || tempy<0 || tempy>=m) || ch[tempx][tempy]>='1') continue; else return false; } return true; } void update(int x,int y,int num){ for(int i=0;i<4;i++){ int tempx=dir[i][0]+x , tempy=dir[i][1]+y; if( tempx >= 0 && tempx < n && tempy>=0 &&tempy<m ) ch[tempx][tempy]+=num; } ch[x][y]+=num; } void printres(){ for(int i=0; i<n; i++) { for(int j=0; j<m; j++) printf("%c",res[i][j]); printf("\n"); } } bool judge(){ for(int i=0;i<m;i++) if(ch[n-1][i]!='0') return false; return true; } void dfs(int x,int y){ if(y>=m) x++,y=0; if( x==n && y==0 ){ if(judge()){ printres(); mark=1; } } if( x<0 || x>=n || mark==1) return ; if(x==0){ if( OK(x,y) ){ update(x,y,-1); res[x][y]='*'; dfs(x,y+1); update(x,y,1); res[x][y]='?'; } res[x][y]='.'; dfs(x,y+1); return ; } if( ch[x-1][y] !='0' && ch[x-1][y] !='1' ) return ; if(ch[x-1][y]=='1'){ res[x][y]='*'; update(x,y,-1); dfs(x,y+1); update(x,y,1); res[x][y]='?'; } else{ res[x][y]='.'; dfs(x,y+1); } return ; } int main () { char dev[100]; int coun=1; scanf("%d",&T); while(T--) { mark=0; scanf("%d%d",&n,&m); for(int i=0; i<n; i++) scanf("%s",&ch[i]); printf("Case %d:\n",coun++); dfs(0,0); } return 0; }
#include <iostream> #include <cstdio> #include <string> #include <cstring> #define MAX 500 using namespace std; char ch[100][100],temp[100][100],res[100][100]; int T,n,m; int dir[][2]= {{-1,0},{1,0},{0,-1},{0,1}}; bool Ok(int tempm){ return temp[0][tempm]=='0' || (tempm!=0&&temp[0][tempm-1]=='0') || (tempm+1<m&&temp[0][tempm+1]=='0'); ///|| (1<n&&temp[1][tempm]=='0') } int main () { char dev[100]; int coun=1; scanf("%d",&T); while(T--) { scanf("%d%d",&n,&m); for(int i=0; i<n; i++) scanf("%s",&ch[i]); int x=(1<<m); printf("Case %d:\n",coun++); int last=n-1; for(int ss=x-1; ss>=0; ss--) { int mark=1; int tempm=m-1; for(int j=0; j<m; j++) res[0][j]='.'; for(int i=0; i<=n-1; i++) strcpy(temp[i],ch[i]); int tempss=ss; for(; tempss>0; tempm--) { if(tempss%2) { res[0][tempm]='*'; if(Ok(tempm)) { mark = 0; last=2; break; } temp[0][tempm]--; if(tempm-1>=0) temp[0][tempm-1]--; if(tempm+1<m) temp[0][tempm+1]--; if(1<n) temp[1][tempm]--; } tempss/=2; } for(int i=1; i<n && mark ; i++) for(int j=0; j<m && mark; j++) { if( temp[i-1][j]!='0' && temp[i-1][j]!='1' ) { mark=0; last=min(n-1,i+2); break; } res[i][j]='.'; if(temp[i-1][j]=='1') { res[i][j]='*'; for(int xxx=0; xxx<4; xxx++) if(i+dir[xxx][0]>=0 && i+dir[xxx][0]<m && j+dir[xxx][1]>=0 && j+dir[xxx][1]<m) { if(temp[ i+dir[xxx][0] ][ j+dir[xxx][1] ]<='0') { mark=0; last=min(n-1,i+2); break; } temp[ i+dir[xxx][0] ][ j+dir[xxx][1] ]--; } temp[i][j]--; } } if(mark==1) { for(int i=0; i<m&&mark; i++) ///判断最后一行 if(temp[n-1][i]!='0') mark=0,last=n-1; for(int i=0; i<n&&mark; i++) { for(int j=0; j<m; j++) printf("%c",res[i][j]); printf("\n"); } if(mark){ break; } } } } return 0; }