• (深搜)UVA


    原题链接:

    https://uva.onlinejudge.org/index.php?option=com_onlinejudge&Itemid=8&category=825&page=show_problem&problem=4475


    题意:

    在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 }
     
  • 相关阅读:
    单片机学习01__跑起你的流水灯
    python2与python3共存
    rpi-kali 搭建网络靶场
    P3388 【模板】割点(割顶)
    P3387 【模板】缩点
    P1069 细胞分裂
    The Unique MST[不严格的次小生成树]
    P3369 【模板】普通平衡树
    Netty的线程模型可不是Reactor这么简单
    SpringBoot+Mybatis+MySQL实现读写分离
  • 原文地址:https://www.cnblogs.com/tak-fate/p/5765968.html
Copyright © 2020-2023  润新知