题目大意:
给定一幅地图,“.”是可以走的空格子,“S”是起点,“D”是终点,“X”是不可以走的墙。问有无这样的一条路,使得从S出发到D恰好在第t秒。并且,不能停留在任何位置。
分析:
因为数据范围很小,所以我使用了爆搜,但是虽然没有TLE,但是却WA了。样例过了,调试感觉也没问题,所以为什么???
#pragma GCC optimize(2)
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
int n,m,t,sx,sy,ex,ey;
char c[10][10];
bool f[10][10],flag;
inline void dfs(int x,int y,int tm){
if(x<1||x>n||y<1||y>m||!f[x][y])return;
if(tm>t)return;
if(x==ex&&y==ey){
if(tm==t)flag=true;
return;
}else{
f[x][y]=false;
dfs(x-1,y,tm+1);
dfs(x,y-1,tm+1);
dfs(x+1,y,tm+1);
dfs(x,y+1,tm+1);
}return;
}
int main(){
while(scanf("%d%d%d",&n,&m,&t)){
flag=false;
memset(f,false,sizeof(f));
if(n==0&&m==0&&t==0)break;
for(int i=1;i<=n;++i){
scanf("%s",c[i]+1);
for(int j=1;j<=m;++j){
if(c[i][j]=='.')f[i][j]=true;
else if(c[i][j]=='S')sx=i,sy=j,f[i][j]=true;
else if(c[i][j]=='D')ex=i,ey=j,f[i][j]=true;
else f[i][j]=false;
}
}
for(int i=1;i<=n;++i){
for(int j=1;j<=m;++j)printf("%c",c[i][j]);
printf("\n");
}
dfs(sx,sy,0);
if(flag)printf("YES\n");
else printf("NO\n");
}
return 0;
}
感谢 某巨佬 \color{red}\text{某巨佬} 某巨佬帮忙调试,对搜索稍微改了改就切了这题。虽然跑了374ms,但是问题不大~
#pragma GCC optimize(2)
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
int n,m,t,sx,sy,ex,ey;
char c[10][10];
bool f[10][10],flag;
inline void dfs(int x,int y,int tm){//爆搜
if(flag)return;//找到了就return可以快不少
if(x==ex&&y==ey){
if(tm==t)flag=true;
return;
}f[x][y]=0;
if(x-1>=1&&f[x-1][y]){
f[x-1][y]=0;
dfs(x-1,y,tm+1);
f[x-1][y]=1;
}
if(y-1>=1&&f[x][y-1]){
f[x][y-1]=0;
dfs(x,y-1,tm+1);
f[x][y-1]=1;
}
if(x+1<=n&&f[x+1][y]){
f[x+1][y]=0;
dfs(x+1,y,tm+1);
f[x+1][y]=1;
}
if(y+1<=m&&f[x][y+1]){
f[x][y+1]=0;
dfs(x,y+1,tm+1);
f[x][y+1]=1;
}
return;
}
int main(){
while(scanf("%d%d%d",&n,&m,&t)){
if(n==0&&m==0&&t==0)break;
flag=false;
memset(f,false,sizeof(f));
for(int i=1;i<=n;++i){
scanf("%s",c[i]+1);
for(int j=1;j<=m;++j){
if(c[i][j]=='.')f[i][j]=true;
if(c[i][j]=='S')sx=i,sy=j,f[i][j]=true;
if(c[i][j]=='D')ex=i,ey=j,f[i][j]=true;
}
}
f[sx][sy]=0;//标记起点
dfs(sx,sy,0);
if(flag)printf("YES\n");
else printf("NO\n");
}
return 0;
}
关于奇偶剪枝:
在爆搜的“if(flag)return;”下一行加上:
if((t-tm)<mhd||((t-tm-mhd)&1))return;
其中——
#define mhd abs(ex-x)+abs(ey-y)
加上曼哈顿距离的奇偶剪枝之后又快了100ms左右,挺好的。
因为比较简单我就不废话了。
不知道之前为什么WA了,也许是没标记初始位置和搜索时没回溯吧。
网上还有不少高级的剪枝操作,不过我觉得水过这题就行了,想进一步提升自己的读者请自行查找吧~