DFS+多回溯--poj3009
这道题题意是很有趣的,我记得在勇者斗恶龙六里面有一点,在一个有冰的洞穴里面,人物的移动方式就是这道题所说的方式,不过这道题有一个特殊之处,就是人物碰到墙的同时会在墙面前停下开,同时,面前的墙会消失掉,这就需要我们在遍历时要做好回溯
这道题是要求最少步数,所以一开始我是想用bfs,但是题目有个条件,就是步数不能超过10,那么这时其实bfs也很快的,而且地图是20*20的,所以就用更好写的dfs啦,不过我觉得bfs应该也是可以的。
用dfs时要特别特别特别注意好回溯
但是注意,visit数组肯定是要不得,上一篇博文里,我因为bfs没加visit数组吃了大亏,而这道题我就直接避开了visit,原因的话,如果你思考过这道题,我相信你会明白的。
我的dfs里面就是对当前节点分别往上下左右搜索,我以我代码中往上搜索的部分为例讲解一下这道题的回溯
for(int i1=x;i1>=1;i1--){//向上搜索 if(map[i1][y]==3){ ans=min(ans,++steps); //stpes+1不难理解 steps--; //这个解同当前ans比较之后,该回溯了,我们先把steps还原 return; //回溯 } if(map[i1][y]==1 && (i1+1)==x) break; if(map[i1][y]==1 && (i1+1)!=x){ steps++; if(steps>ans || steps>10){ steps--; //此路不通 回溯前steps-- return; //回溯 } map[i1][y]=0; dfs(i1+1,y); //上边的两种回溯退回到了这里。但是注意,并不一定退回到了“往上搜索”的这一句哦,也可能是退回到了“往左右下搜索”的这一行 map[i1][y]=1; steps--; break; //因为从当前dfs的出发点,往上搜索已经得到解,因此break,去试试往别的方向走 } }
完整代码:
#include<iostream> #include<cstring> #include<queue> using namespace std; const int maxn=20+5; int l,h,bx,by,ex,ey; int map[maxn][maxn]; int ans,steps; void dfs(int x,int y){ for(int i1=x;i1>=1;i1--){//向上搜索 if(map[i1][y]==3){ ans=min(ans,++steps); steps--; return; } if(map[i1][y]==1 && (i1+1)==x) break; if(map[i1][y]==1 && (i1+1)!=x){ steps++; if(steps>ans || steps>10){ steps--; return; } map[i1][y]=0; dfs(i1+1,y); map[i1][y]=1; steps--; break; } } for(int i2=x;i2<=h;i2++){//向下搜索 if(map[i2][y]==3){ ans=min(ans,++steps); steps--; return; } if(map[i2][y]==1 && (i2-1)==x) break; if(map[i2][y]==1 && (i2-1)!=x){ steps++; if(steps>ans || steps>10){ steps--; return; } map[i2][y]=0; dfs(i2-1,y); map[i2][y]=1; steps--; break; } } for(int i3=y;i3>=1;i3--){//向左搜索 if(map[x][i3]==3){ ans=min(ans,++steps); steps--; return; } if(map[x][i3]==1 && (i3+1)==y) break; if(map[x][i3]==1 && (i3+1)!=y){ steps++; if(steps>ans || steps>10){ steps--; return; } map[x][i3]=0; dfs(x,i3+1); map[x][i3]=1; steps--; break; } } for(int i4=y;i4<=l;i4++){//向右搜索 if(map[x][i4]==3){ ans=min(ans,++steps); steps--; return; } if(map[x][i4]==1 && (i4-1)==y) break; if(map[x][i4]==1 && (i4-1)!=y){ steps++; if(steps>ans || steps>10){ steps--; return; } map[x][i4]=0; dfs(x,i4-1); map[x][i4]=1; steps--; break; } } } int main(){ freopen("in.txt","r",stdin); while(cin>>l>>h && l!=0 ){ ans=10000; steps=0; for(int i=1;i<=h;i++){ for(int j=1;j<=l;j++){ cin>>map[i][j]; if(map[i][j]==2){ bx=i; by=j; } if(map[i][j]==3){ ex=i; ey=j; } } } dfs(bx,by); if(ans>10) cout<<-1<<endl; else cout<<ans<<endl; } return 0; }
柳暗花明又一村