这道题折腾了接近两天时间,快把我逼疯了,不过收获巨大!!
我的第一个版本写的超烂,虽然写的很细致,如果能ac的话效率应该会很高,但的很乱,冗余度也很高,在加上自己的渣水平,debug了一天也没ac,只好推倒重来。
反思了一下,自己在写第一个版本的时候,完全是为了追求速度,几乎放弃了对代码可读性及风格的要求,这样做真是得不偿失,以后一定要注意!下面会附上第一个版本的代码。
相比之下,第二个版本由于吸取了教训,当然也包括借鉴别人的代码,无论是代码可读性(或者叫可调试性),还是效率,都要更高。
先说一下pruning:
1、四个方向上 F O I 都要满足特殊要求,O I要一一对应。
2、先用qsort对piece进行排列,这样做的便于后面dfs剪枝。
3、dfs的时候,如果一个piece不能放在这个位置,就把它记录下来,如果碰到相同的piece就continue,这个剪枝非常重要,基本上决定了会不会超时。
也基本掌握了stdlib里qsort的用法(在这里也卡了好久,基本功是硬伤啊。。),主要就是cmp函数的写法:对于cmp函数,如果 比较函数返回大于0,qsort就认为 a>b , 如果比较函数返回等于0 qsort就认为a 和b 这两个元素相等,返回小于零 qsort就认为 a<b。
这个和stl里的cmp不同,stl里的只要求cmp函数能判断小于关系,不过我尝试了一下好像stl里的sort不适合排列字符串。
最重要的收获其实是,做题时,最重要的是心态,心态好,一切都好说,如果只是为了做题而做题,或者心情暴躁不安,基本上就是在磨时间,以后一定要做出改变
另外,从这道题开始,我也准备放弃vc改用codeblocks,因为调的过程中发现了它们的一个不同:我在memset数组时,数值写大了,结果vc下没有影响其他变量而codeblocks影响了。。。这虽然主要是自己的错,但还是换过避免一些问题吧。
版本一:
#include<cstdio>
#include<cstring>
#include<algorithm>
#define N 10
using namespace std;
char corner[4][10],border[4][N-2][10],center[(N-2)*(N-2)][10],vis[5][(N-2)*(N-2)],input[N][10],area[N][N][10],visit[N][N];
int n,m,corners1,corners2,corners3,corners4,borders1,borders2,borders3,borders4,centers;
int ok;
int judge1()
{
int i,j,help[8]={0,1,2,3,4,5,6,7};
for(i=0;i<m;i++)
if(input[i][0]!='F'||input[i][2]!='F')
return 0;
//qsort(input,m,5,cmp);
do
{
if(input[help[0]][0]=='F'&&input[help[0]][2]=='F'&&input[help[0]][3]=='F'&&input[help[m-1]][0]=='F'&&input[help[m-1]][2]=='F'&&input[help[m-1]][1]=='F')
{
for(i=1;i<m;i++)
{
if(!(input[help[i-1]][1]=='O'&&input[help[i]][3]=='I'||input[help[i-1]][1]=='I'&&input[help[i]][3]=='O'))
break;
}
if(i==m)
return 1;
}
}while(next_permutation(help,help+m));
return 0;
}
int judge2()
{
//printf("test");
int i,j,help[8]={0,1,2,3,4,5,6,7};
for(i=0;i<n;i++)
if(input[i][1]!='F'||input[i][3]!='F')
return 0;
//qsort(input,n,5,cmp);
do
{
if(input[help[0]][0]=='F'&&input[help[0]][1]=='F'&&input[help[0]][3]=='F'&&input[help[n-1]][1]=='F'&&input[help[n-1]][2]=='F'&&input[help[n-1]][3]=='F')
{
for(i=1;i<n;i++)
{
if(!(input[help[i-1]][2]=='O'&&input[help[i]][0]=='I'||input[help[i-1]][2]=='I'&&input[help[i]][0]=='O'))
break;
}
//printf("test%d ",i);
if(i==n)
return 1;
}
}while(next_permutation(help,help+n));
return 0;
}
int nextx(int x,int y)
{
if(y==m-1)
return x+1;
else
return x;
}
int nexty(int y)
{
if(y==m-1)
return 0;
else
return y+1;
}
int judge(int x,int y,char p[5])
{
int i,j;
if(x==0)
{
int vector[3][2]={{0,1},{1,0},{0,-1}},flag[3][2]={{3,1},{0,2},{1,3}};
for(i=0;i<3;i++)
{
if(visit[x+vector[i][0]][y+vector[i][1]])
{
if(!(area[x+vector[i][0]][y+vector[i][1]][flag[i][0]]=='I'&&p[flag[i][1]]=='O'||area[x+vector[i][0]][y+vector[i][1]][flag[i][0]]=='O'&&p[flag[i][1]]=='I'))
return 0;
}
}
return 1;
}
else if(y==m-1)
{
int vector[3][2]={{-1,0},{1,0},{0,-1}},flag[3][2]={{2,0},{0,2},{1,3}};
for(i=0;i<3;i++)
{
if(visit[x+vector[i][0]][y+vector[i][1]])
{
if(!(area[x+vector[i][0]][y+vector[i][1]][flag[i][0]]=='I'&&p[flag[i][1]]=='O'||area[x+vector[i][0]][y+vector[i][1]][flag[i][0]]=='O'&&p[flag[i][1]]=='I'))
return 0;
}
}
return 1;
}
else if(x==n-1)
{
int vector[3][2]={{-1,0},{0,1},{0,-1}},flag[3][2]={{2,0},{3,1},{1,3}};
for(i=0;i<3;i++)
{
if(visit[x+vector[i][0]][y+vector[i][1]])
{
if(!(area[x+vector[i][0]][y+vector[i][1]][flag[i][0]]=='I'&&p[flag[i][1]]=='O'||area[x+vector[i][0]][y+vector[i][1]][flag[i][0]]=='O'&&p[flag[i][1]]=='I'))
return 0;
}
}
return 1;
}
else if(y==0)
{
int vector[3][2]={{-1,0},{0,1},{1,0}},flag[3][2]={{2,0},{3,1},{0,2}};
for(i=0;i<3;i++)
{
if(visit[x+vector[i][0]][y+vector[i][1]])
{
if(!(area[x+vector[i][0]][y+vector[i][1]][flag[i][0]]=='I'&&p[flag[i][1]]=='O'||area[x+vector[i][0]][y+vector[i][1]][flag[i][0]]=='O'&&p[flag[i][1]]=='I'))
return 0;
}
}
return 1;
}
else
{
int vector[4][2]={{-1,0},{0,1},{1,0},{0,-1}},flag[4][2]={{2,0},{3,1},{0,2},{1,3}};
for(i=0;i<4;i++)
{
if(visit[x+vector[i][0]][y+vector[i][1]])
{
if(!(area[x+vector[i][0]][y+vector[i][1]][flag[i][0]]=='I'&&p[flag[i][1]]=='O'||area[x+vector[i][0]][y+vector[i][1]][flag[i][0]]=='O'&&p[flag[i][1]]=='I'))
return 0;
}
}
return 1;
}
}
void dfs(int x,int y)
{
if(ok==1)
return ;
if(x==n&&y==0)
{ //2*2以及其他的情况
if((area[0][0][1]=='I'&&area[0][1][3]=='O'||area[0][0][1]=='O'&&area[0][1][3]=='I')
&&(area[0][0][2]=='I'&&area[1][0][0]=='O'||area[0][0][2]=='O'&&area[1][0][0]=='I')
&&(area[0][m-1][3]=='I'&&area[0][m-2][1]=='O'||area[0][m-1][3]=='O'&&area[0][m-2][1]=='I')
&&(area[0][m-1][2]=='I'&&area[1][m-1][0]=='O'||area[0][m-1][2]=='O'&&area[1][m-1][0]=='I')
&&(area[n-1][m-1][0]=='I'&&area[n-2][m-1][2]=='O'||area[n-1][m-1][0]=='O'&&area[n-2][m-1][2]=='I')
&&(area[n-1][m-1][3]=='I'&&area[n-1][m-2][1]=='O'||area[n-1][m-1][3]=='O'&&area[n-1][m-2][1]=='I')
&&(area[n-1][0][1]=='I'&&area[n-1][1][3]=='O'||area[n-1][0][1]=='O'&&area[n-1][1][3]=='I')
&&(area[n-1][0][0]=='I'&&area[n-2][0][2]=='O'||area[n-1][0][0]=='O'&&area[n-2][0][2]=='I'))
ok=1;
return ;
}
int i,j,errors=0;
char error[(N-2)*(N-2)][5];
if(visit[x][y])
{
dfs(nextx(x,y),nexty(y));
if(ok==1)
return ;
}
else if(x==0)
{
for(i=0;i<m-2;i++)
{
if(!vis[1][i])
{
for(j=0;j<errors;j++)
{
if(strcmp(error[j],border[0][i])==0)
goto next1;
}
if(judge(x,y,border[0][i]))
{
vis[1][i]=1;
visit[x][y]=1;
strcpy(area[x][y],border[0][i]);
dfs(nextx(x,y),nexty(y));
if(ok==1)
return ;
strcpy(error[errors++],border[0][i]);
vis[1][i]=0;
visit[x][y]=0;
}
}
next1:;
}
}
else if(y==m-1)
{
for(i=0;i<n-2;i++)
{
if(!vis[2][i])
{
for(j=0;j<errors;j++)
{
if(strcmp(error[j],border[1][i])==0)
goto next2;
}
if(judge(x,y,border[1][i]))
{
vis[2][i]=1;
strcpy(area[x][y],border[1][i]);
visit[x][y]=1;
dfs(nextx(x,y),nexty(y));
if(ok==1)
return ;
strcpy(error[errors++],border[1][i]);
vis[2][i]=0;
visit[x][y]=0;
}
}
next2:;
}
}
else if(x==n-1)
{
for(i=0;i<m-2;i++)
{
if(!vis[3][i])
{
for(j=0;j<errors;j++)
{
if(strcmp(error[j],border[2][i])==0)
goto next3;
}
if(judge(x,y,border[2][i]))
{
vis[3][i]=1;
strcpy(area[x][y],border[2][i]);
visit[x][y]=1;
dfs(nextx(x,y),nexty(y));
if(ok==1)
return ;
strcpy(error[errors++],border[2][i]);
vis[3][i]=0;
visit[x][y]=0;
}
}
next3:;
}
}
else if(y==0)
{
for(i=0;i<n-2;i++)
{
if(!vis[4][i])
{
for(j=0;j<errors;j++)
{
if(strcmp(error[j],border[3][i])==0)
goto next4;
}
if(judge(x,y,border[3][i]))
{
vis[4][i]=1;
strcpy(area[x][y],border[3][i]);
visit[x][y]=1;
dfs(nextx(x,y),nexty(y));
if(ok==1)
return ;
strcpy(error[errors++],border[3][i]);
vis[4][i]=0;
visit[x][y]=0;
}
}
next4:;
}
}
else
{
for(i=0;i<(m-1)*(n-1);i++)
{
if(!vis[0][i])
{
for(j=0;j<errors;j++)
{
if(strcmp(error[j],center[i])==0)
goto next5;
}
if(judge(x,y,center[i]))
{
vis[0][i]=1;
strcpy(area[x][y],center[i]);
visit[x][y]=1;
dfs(nextx(x,y),nexty(y));
if(ok==1)
return ;
strcpy(error[errors++],center[i]);
vis[0][i]=0;
visit[x][y]=0;
}
}
next5:;
}
}
}
int main()
{
int i,j,help,inputs,oo[4],ii[4],flat;
char s[5];
while(scanf("%d%d%*c",&n,&m)&&n+m)
{
//getchar();
corners1=corners2=corners3=corners4=borders1=borders2=borders3=borders4=centers=0;
inputs=0;
ok=flat=0;
memset(oo,0,16);
memset(ii,0,16);
memset(vis,0,40*(N-2)*(N-2));
memset(visit,0,2*(N)*(N)*4);
for(i=0;i<n*m;i++)
{
help=0;
scanf("%s",s);
for(j=0;j<4;j++)
{
if(s[j]=='F')
{
help++;
flat++;
}
if(s[j]=='O')
oo[j]++;
if(s[j]=='I')
ii[j]++;
}
if(m==1&&n==1)
{
if(help==4)
printf("YES\n");
else
printf("NO\n");
goto next;
}
if(n==1)
{
strcpy(input[inputs++],s);
}
else if(m==1)
{
strcpy(input[inputs++],s);
}
else
{
if(help>=3)
{
printf("NO\n");
goto next;
}
if(s[0]=='F'&&s[3]=='F')
{
strcpy(corner[0],s);
corners1++;
}
else if(s[0]=='F'&&s[1]=='F')
{
strcpy(corner[1],s);
corners2++;
}
else if(s[2]=='F'&&s[1]=='F')
{
strcpy(corner[2],s);
corners3++;
}
else if(s[2]=='F'&&s[3]=='F')
{
strcpy(corner[3],s);
corners4++;
}
else if(s[0]=='F')
{
strcpy(border[0][borders1++],s);
}
else if(s[1]=='F')
{
strcpy(border[1][borders2++],s);
}
else if(s[2]=='F')
{
strcpy(border[2][borders3++],s);
}
else if(s[3]=='F')
{
strcpy(border[3][borders4++],s);
}
else
strcpy(center[centers++],s);
}
}
if(n==1)
{
if(judge1()&&flat==2*(m+n))
printf("YES\n");
else
printf("NO\n");
}
else if(m==1)
{
if(judge2()&&flat==2*(m+n))
printf("YES\n");
else
printf("NO\n");
}
else
{
if(ii[0]!=oo[2]||ii[1]!=oo[3]||ii[2]!=oo[0]||ii[3]!=oo[1]||flat!=2*(m+n))
{
printf("NO\n");
goto next;
}
if(corners1!=1||corners2!=1||corners3!=1||corners4!=1||borders1!=m-2||borders2!=n-2||borders3!=m-2||borders4!=n-2||centers!=(m-2)*(n-2))
{
printf("NO\n");
goto next;
}
strcpy(area[0][0],corner[0]);
visit[0][0]=1;
strcpy(area[0][m-1],corner[1]);
visit[0][m-1]=1;
strcpy(area[n-1][m-1],corner[2]);
visit[n-1][m-1]=1;
strcpy(area[n-1][0],corner[3]);
visit[n-1][0]=1;
dfs(0,0);
/*printf("%d ",corners1);
printf("%d ",corners2); printf("%d ",corners3); printf("%d ",corners4);
printf("%d ",borders1);
printf("%d ",borders2); printf("%d ",borders3); printf("%d ",borders4);
printf("\n%d ",centers);*/
if(ok==1)
printf("YES\n");
else
printf("NO\n");
}
next:;
//gets(s);
}
return 0;
}
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cstdlib>
#define SIZE 8
using namespace std;
int n,m,ok;
char s[SIZE*SIZE][10],vis[SIZE*SIZE],area[SIZE][SIZE];
int cmp(const void *p,const void *q)
{
/*if(strcmp((char *)p,(char *)q)!=0)
return 1;
else
return 0;*/
return strcmp((char *)p,(char *)q);//写错一次
}
int nextx(int x,int y)
{
if(y==m-1)
return x+1;
else
return x;
}
int nexty(int y)
{
if(y==m-1)
return 0;
else
return y+1;
}
int judge(int x,int y,int index)
{
if((x==0&&s[index][0]!='F')||(x==n-1&&s[index][2]!='F')||(y==0&&s[index][3]!='F')||(y==m-1&&s[index][1]!='F'))
return 0;
int i,j,xx,yy,vector1[4][2]={{-1,0},{0,1},{1,0},{0,-1},},vector2[4][2]={{2,0},{3,1},{0,2},{1,3},};
for(i=0;i<4;i++)
{
xx=x+vector1[i][0],yy=y+vector1[i][1];
if(xx>=0&&xx<n&&yy>=0&&yy<m)//存在少许冗余
{
if(area[xx][yy]!=-1)//area写错一次
{
if(!((s[area[xx][yy]][vector2[i][0]]=='I'&&s[index][vector2[i][1]]=='O')||(s[area[xx][yy]][vector2[i][0]]=='O'&&s[index][vector2[i][1]]=='I'))||(s[index][vector2[i][1]]=='F'))
return 0;
}
else//少写一次
{
if(s[index][vector2[i][1]]=='F')
return 0;
}
}
}
return 1;
}
void dfs(int x,int y)
{
if(ok==true)
return ;
if(x==n&&y==0)
{
ok=true;
return ;
}
int i,j;
char help[10]="a";
for(i=0;i<m*n;i++)
{
if(!vis[i]&&strcmp(help,s[i])!=0&&judge(x,y,i))
{
vis[i]=1;
area[x][y]=i;
strcpy(help,s[i]);//tricks
dfs(nextx(x,y),nexty(y));
if(ok==true)
return ;
vis[i]=0;
area[x][y]=-1;
}
}
}
int main()
{
int i,j;
int ff[4],ii[4],oo[4];
while(scanf("%d%d",&n,&m)&&m+n)
{
memset(ff,0,16);
memset(ii,0,16);
memset(oo,0,16);
memset(vis,0,SIZE*SIZE);
memset(area,-1,SIZE*SIZE);
ok=false;
for(i=0;i<m*n;i++)
{
scanf("%s",s[i]);
for(j=0;j<4;j++)
{
if(s[i][j]=='F')
ff[j]++;
else if(s[i][j]=='I')
ii[j]++;
else if(s[i][j]=='O')
oo[j]++;
}
}
if(ff[0]!=m||ff[1]!=n||ff[0]!=ff[2]||ff[1]!=ff[3]||ii[0]!=oo[2]||ii[1]!=oo[3]||ii[2]!=oo[0]||ii[3]!=oo[1])
{
printf("NO\n");
goto next;
}
//printf("%d %d",m,n);
qsort(s,m*n,sizeof(s[0]),cmp);
// puts("");
//for(i=0;i<m*n;i++)
// puts(s[i]);
dfs(0,0);
if(ok==1)
printf("YES\n");
else
printf("NO\n");
next:;
}
return 0;
}