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;
}
浙公网安备 33010602011771号