这道题磨了我一个下午,虽然在大神帮助下完成,要注意的东西太多,之前还用了宽搜,那是每看懂题目意思,宽搜是找到一条最短路,而这道题不一定是最短路,要在规定的时间到达,换句话说就是有规定的步数,走了的不能再走。
写题中遇到以下几个问题:
1.对于深搜还是没有完全理解,由于是递归,所以每次的函数体应该都是一样的,之前把不该改变的起点步数清零放在递归函数里,导致错误。
2.对于我之前有点画蛇添足,我又加了个结构体,存迷宫每个点的横纵坐标和信息,然后我在递归结束条件那里直接判断的,但是我在赋值又没有对每个点赋值,导致出错,太粗心了。看下面的错误!!
typedef struct dd{ int a,b; char sr; }dd; bool dfs(dd t,int dis){ if((t.sr=='D')&&(dis==ti)) return true; for(int i=0;i<4;i++){ s.a=t.a+x[i]; s.b=t.b+y[i];//少了一个s.sr=maze[s.a][s.b],太粗心拉 }
3.这题的特殊是在递归时返回上层应返回可不可行,而不仅仅是继续搜下去,所以有如下:
if(dfs(s,dis+1)) return true;
4.全部完成了以后还是超时,要剪枝!由曼哈顿距离,总的耗时=曼哈顿距离+多余的路,并且多余的路一定是个偶数,否则不能到达。曼哈顿距离=|起点横坐标-终点横坐标|+|起点纵坐标-终点纵坐标|。然后这题就好啦><
#include<stdio.h> #include<iostream> #include<string.h> #include<queue> #include<math.h> #include<algorithm> using namespace std; int x[4]={-1,0,0,1}; int y[4]={0,-1,1,0}; char maze[10][10]; int vis[10][10]; int ti,n,m; typedef struct dd{ int a,b; char sr; }dd; dd st,en; bool dfs(dd t,int dis){ if((maze[t.a][t.b]=='D')&&(dis==ti))//之前在这犯错误,改了一下 return true; if(dis>ti) return false; dd s; for(int i=0;i<4;i++){ s.a=t.a+x[i]; s.b=t.b+y[i]; if(s.a>=0&&s.a<n&&s.b>=0&&s.b<m&&maze[s.a][s.b]!='X'&&!vis[s.a][s.b]){ vis[s.a][s.b]=1; if(dfs(s,dis+1)) return true; vis[s.a][s.b]=0; } } return false; } int main(){ while(scanf("%d%d%d",&n,&m,&ti)!=EOF){ if(n==0&&m==0&&ti==0) break; getchar(); memset(vis,0,sizeof(vis)); for(int i=0;i<n;i++){ for(int j=0;j<m;j++) scanf("%c",&maze[i][j]); getchar(); } for(int i=0;i<n;i++){ for(int j=0;j<m;j++){ if(maze[i][j]=='S'){ st.sr=maze[i][j]; st.a=i; st.b=j; } else if(maze[i][j]=='D'){ en.a=i; en.b=j; } } } vis[st.a][st.b]=1; if(((ti-(st.a-en.a+st.b-en.b))%2==0)&&dfs(st,0))//剪枝,否则超时 cout<<"YES"<<endl; else cout<<"NO"<<endl; } return 0; }