原题链接:
题意:
在m*n的地图上,有障碍物(1)和空地(0),机器人要通过走上下左右四个方向从左上角(1,1)走到右下角(n,m),但不能连续超过k个障碍,要求最短步数。
感悟:
刷紫书遇到的一题,一开始还很轻视的写了一个dfs,发现过不了样例,之后才发现是连续空格,稍微改下,过了样例就提交了,结果是TLE。评估下,要么就是dfs中判断的不够严格,需要剪枝,要么就是这题dfs必定超时,只能用bfs。先尝试前一种,发现平从我定义的状态中以我的水无法再优化剪枝,思考了一下bfs,感觉按照我dfs的思路,写出来的bfs必定WA。最后查看了题解,发现dfs,bfs都有人写,才知道自己在搜索上的造诣依然浅薄。
分析:
按照最基本的搜索题,我们都要定义一个vis二维数组,记录该点是否走过,并通过它达到回溯的目的。
但在这题中,机器人走路会有更多的分支选择,比如在走到同一点,有两种同一步数的走法,但是到达这一点所破除的障碍数量却不同,在这里我们需要选择障碍物更少的,因为很有可能在以后破除障碍能更快到达终点。用一个vis[][][]三维数组就可以记录这样一种状态,前两维记录坐标,第三维记录已经破除障碍物的数量,数组值表示走的步数,与上边一样的道理,到达相同点并且破除障碍物数量相同时,应该选择步数最小的。
代码:
1 #include <iostream> 2 #include <cstdio> 3 #include <cstring> 4 #include <vector> 5 #include <set> 6 #include <map> 7 #include <algorithm> 8 #include <string> 9 #include <queue> 10 #include <cmath> 11 #include <stack> 12 #include <cctype> 13 #include <list> 14 15 #define ll long long 16 #define ull unsigned long long 17 #define VNAME(name) (#name) 18 #define debug(a) cout<<VNAME(a)<<" = "<<(a)<<endl; 19 20 using namespace std; 21 22 const int maxn = 100010; 23 const int inf = 1 << 30; 24 25 int maps[21][21]; 26 int vis[21][21][21]; 27 int dx[4]={1,0,-1,0}; 28 int dy[4]={0,1,0,-1}; 29 int n,m,k; 30 int ans; 31 32 int dfs(int x,int y,int step,int pok){ 33 if(x==n&&y==m){ 34 return step; 35 } 36 int ans=inf; 37 for(int i=0;i<4;i++){ 38 int tx=x+dx[i]; 39 int ty=y+dy[i]; 40 int tp=pok; 41 if(maps[tx][ty]==1)tp++; 42 else tp=0; 43 if(tx>=1&&tx<=n&&ty>=1&&ty<=m){ 44 if((vis[tx][ty][tp]<0||vis[tx][ty][tp]>step+1)&&tp<=k){ 45 vis[tx][ty][tp]=step+1; 46 ans=min(ans,dfs(tx,ty,step+1,tp)); 47 } 48 } 49 } 50 return ans; 51 } 52 53 int main() { 54 //iostream::sync_with_stdio(false); 55 56 #ifndef ONLINE_JUDGE 57 freopen("in.txt","r",stdin); 58 //freopen("out.txt","w",stdout); 59 #endif 60 int t; 61 scanf("%d",&t); 62 while(t--){ 63 scanf("%d%d%d",&n,&m,&k); 64 for(int i=1;i<=n;i++){ 65 for(int j=1;j<=m;j++){ 66 scanf("%d",&maps[i][j]); 67 } 68 } 69 memset(vis,-1,sizeof(vis)); 70 int ans=dfs(1,1,0,0); 71 if(ans==inf){ 72 puts("-1"); 73 } 74 else{ 75 printf("%d ",ans); 76 } 77 } 78 return 0; 79 }