dfs个人第一题,费尽千辛万苦,终于AC,一AC解万愁。果然自己亲自敲代码的过程学到不少。必作一总结。
先附代码,修改比较多,so,比较丑。
#include<stdio.h>
#include<string.h>
int pan[30][30];
int fa[1000][2];
int count;
char alp[30]={'A','B','C','D','E','F','G','H','I','J','K','L','M','N','O','P','Q','R','S','T','U','V','W','X','Y','Z'};
int dfs(int i,int j,int cnt,int n)
{
if(cnt==n){fa[cnt][0]=i;fa[cnt][1]=j;return 1;}
fa[cnt][0]=i;fa[cnt][1]=j;
pan[i][j]=0;
if(i-1>0&&j-2>0&&pan[i-1][j-2]==1)
{
// pan[i-1][j-2]=0;
if(dfs(i-1,j-2,cnt+1,n))
{return 1;}
//else pan[i-1][j-2]=1;
}
if(i+1>0&&j-2>0&&pan[i+1][j-2]==1)
{
// pan[i+1][j-2]=0;
if(dfs(i+1,j-2,cnt+1,n))
{return 1;}
//else pan[i+1][j-2]=1;
}
if(i-2>0&&j-1>0&&pan[i-2][j-1]==1)
{
// pan[i-2][j-1]=0;
if(dfs(i-2,j-1,cnt+1,n))
{return 1;}
// else pan[i-2][j-1]=1;
}
if(i+2>0&&j-1>0&&pan[i+2][j-1]==1)
{
// pan[i+2][j-1]=0;
if(dfs(i+2,j-1,cnt+1,n))
{return 1;}
//else pan[i+2][j-1]=1;
}
if(i-2>0&&j+1>0&&pan[i-2][j+1]==1)
{
//pan[i-2][j+1]=0;
if(dfs(i-2,j+1,cnt+1,n))
{return 1;}
//else pan[i-2][j+1]=1;
}
if(i+2>0&&j+1>0&&pan[i+2][j+1]==1)
{
// pan[i+2][j+1]=0;
if(dfs(i+2,j+1,cnt+1,n))
{return 1;}
//else pan[i+2][j+1]=1;
}
if(i-1>0&&j+2>0&&pan[i-1][j+2]==1)
{
//pan[i-2][j+2]=0;
if(dfs(i-1,j+2,cnt+1,n))
{return 1;}
//else pan[i-2][j+2]=1;
}
if(i+1>0&&j+2>0&&pan[i+1][j+2]==1)
{
// pan[i+1][j+2]=0;
if(dfs(i+1,j+2,cnt+1,n))
{return 1;}
// else pan[i+1][j+2]=1;
}
pan[i][j]=1;return 0;
}
int main()
{
int case_num;
scanf("%d",&case_num);
int qq=1;
for(;qq<=case_num;qq++)
{
int p,q;
scanf("%d%d",&p,&q);
if(p==1&&q==1)
{
printf("Scenario #%d:\n",qq);
printf("A1\n");
printf("\n");
continue;
}
memset(pan,0,sizeof(pan));
memset(fa,0,sizeof(fa));
for(int i=1;i<=p;i++)
for(int j=1;j<=q;j++)
pan[i][j]=1;
int ans=dfs(1,1,1,p*q);
if(ans)
{
printf("Scenario #%d:\n",qq);
for(int i=1;i<=p*q;i++)
printf("%c%d",alp[fa[i][1]-1],fa[i][0]);
printf("\n\n");
}
else
{
printf("Scenario #%d:\n",qq);
printf("impossible\n\n");
}
}
return 0;
}
几点关键总结:
1.
先从基本的说起。dfs的思路,其实可以更进一步改进代码质量,详情见此题相关discuss。自己分八个dfs代码长度弄的其实比较长。
单纯的遍历其实有好多判断方法,自己受LRJ代码风格影响,一般习惯用cnt与n的比较,当n==cnt时一般作为自己的判断条件。见网上还有人直接for()之后若无满足情况自动return false;
2.
自己真正不会的地方在于打印路径。
最开始的思路是建了全局变量fa[MAX][2],可dfs每次过程中都会改变fa的值,并且自己建立的全局变量count的值也会在每次调用中改变。
通过自己的代码中注释的部分也能看出自己的思路变化过程。
后来一系列改进,参考网上某大神思路,
fa[cnt][0]=i;fa[cnt][1]=j;
用上述这种形式,cnt是当前,解决了我一个最大的疑问,这样的话每次遍历都会修改fa的值,而不至于像上次count那样一直累加。
最后强调一点若最后不满足的话,要 pan[i][j]=1;return 0; 再把pan[i][j]的标记改回来。
3.
PS:自己的推判是正确的,每次若能遍历完,必可从A1开始。
PS:字典序!
PS:题目的输出有两个空格!