zoukankan      html  css  js  c++  java
  • DFS(5)——hdu1728逃离迷宫

    一、题目回顾

    题目链接:逃离迷宫

    Problem Description
      给定一个m × n (m行, n列)的迷宫,迷宫中有两个位置,gloria想从迷宫的一个位置走到另外一个位置,当然迷宫中有些地方是空地,gloria可以穿越,有些地方是障碍,她必须绕行,从迷宫的一个位置,只能走到与它相邻的4个位置中,当然在行走过程中,gloria不能走到迷宫外面去。令人头痛的是,gloria是个没什么方向感的人,因此,她在行走过程中,不能转太多弯了,否则她会晕倒的。我们假定给定的两个位置都是空地,初始时,gloria所面向的方向未定,她可以选择4个方向的任何一个出发,而不算成一次转弯。gloria能从一个位置走到另外一个位置吗?
     
    Input
      第1行为一个整数t (1 ≤ t ≤ 100),表示测试数据的个数,接下来为t组测试数据,每组测试数据中,
      第1行为两个整数m, n (1 ≤ m, n ≤ 100),分别表示迷宫的行数和列数,接下来m行,每行包括n个字符,其中字符'.'表示该位置为空地,字符'*'表示该位置为障碍,输入数据中只有这两种字符,每组测试数据的最后一行为5个整数k, x1, y1, x2, y2 (1 ≤ k ≤ 10, 1 ≤ x1, x2 ≤ n, 1 ≤ y1, y2 ≤ m),其中k表示gloria最多能转的弯数,(x1, y1), (x2, y2)表示两个位置,其中x1,x2对应列,y1, y2对应行。
     
    Output
      每组测试数据对应为一行,若gloria能从一个位置走到另外一个位置,输出“yes”,否则输出“no”。
     
    Sample Input
    2
    5 5
    ...**
    *.**.
    .....
    .....
    *....
    1 1 1 1 3
    5 5
    ...**
    *.**.
    .....
    .....
    *....
    2 1 1 1 3
     
    Sample Output
    no
    yes
     
    题意:小明在点1(x1 , y1),请问他能在转弯次数不大于k的情况下到达点2(x2 , y2)吗 ?

    二、解题思路

    • 据说是经典BFS
    • DFS+剪枝
    • 转弯数

    三、代码

     1 //dfs+剪枝 
     2 //根据下一点如果遍历过而且转弯数小于当前点到达下一点的转弯数(其他情况类似)进行剪枝
     3 #include <iostream>
     4 #include <cstdio>
     5 #include <algorithm>
     6 #include <cstring>
     7 using namespace std;
     8 const int maxn = 1e4+10;
     9 #define INF 0x3f3f3f3f
    10 char a[105][105];
    11 int n,m,k,T,x1,y1,x2,y2;                    //起点坐标(is,js),门的坐标(id,jd) 
    12 int to[4][2]={1,0,-1,0,0,1,0,-1};
    13 int vis[105][105];                        //记录到达某点所需的转弯数
    14 bool flag;
    15 
    16 void dfs(int x,int y,int dir)            //cnt为当前转弯的次数 
    17 {
    18     int mx,my;
    19     if(x==x2 && y==y2){
    20         if(vis[x][y]<=k)
    21             flag = 1;
    22         return;
    23     }
    24     if(vis[x][y]>k)    return;                //大于k时已晕,不行 
    25     //如果(x,y)和终点(x2,y2),既不在同一行也不在同一列,那么要想到终点至少需要转一次,但现在已经转够k次了,故不行
    26     if(vis[x][y]==k && x!=x2 && y!=y2)    return;         
    27     for(int i=0;i<4;i++){
    28         mx = x + to[i][0];
    29         my = y + to[i][1];
    30         if(mx<1 || mx>m || my<1 || my>n)    continue;
    31         if(vis[x][y]>vis[mx][my] || a[mx][my]=='*')        continue;         //这里相等的情况不能剪掉
    32         //这条if和上面的差不多,目的是:如果从(x,y)走一步到(tx,ty)需要转一次话,并且转过之后vis[x][y]+1依然比vis[tx][ty]大的话,也不符合
    33         if(dir!=-1 && i!=dir && vis[mx][my]<vis[x][y]+1)    continue;    
    34         vis[mx][my] = vis[x][y];
    35         if(dir!=-1 && i!=dir){
    36             vis[mx][my]++;
    37         } 
    38         dfs(mx,my,i);
    39         if(flag==1)
    40             return;
    41     }
    42 } 
    43 
    44 int main()
    45 {
    46     cin>>T;
    47     while(T--){
    48         scanf("%d%d",&m,&n);
    49         for(int i=1;i<=m;i++){
    50             getchar();
    51             for(int j=1;j<=n;j++){
    52                 scanf("%c",&a[i][j]);
    53             }
    54         }
    55         getchar();    
    56         cin>>k>>y1>>x1>>y2>>x2;                //注意,这里是先接y,再接x
    57         memset(vis,INF,sizeof(vis));        //因为在dfs()中剪枝要去最小的转弯次数,所以vis要初始化成最大
    58         vis[x1][y1] = 0;                    //转0次弯 
    59         flag = 0;
    60         dfs(x1,y1,-1);
    61         if(flag==1)    printf("yes
    ");
    62         if(flag==0)    printf("no
    ");
    63     }
    64     return 0;
    65 }
  • 相关阅读:
    [codevs 1243][网络提速(最短路分层思想)
    [codevs 1183][泥泞的道路(二分+spfa)
    [codevs 2488]绿豆蛙的归宿(拓扑排序)
    [codevs 1961]躲避大龙(dfs)
    4、userCF和itemCF对比,冷启动
    query简洁弹出层代码
    css 积累1
    localStorage,sessionStorage
    tr th td
    (转存)面向切面编程(AOP)的理解
  • 原文地址:https://www.cnblogs.com/xzxl/p/7302570.html
Copyright © 2011-2022 走看看