zoukankan      html  css  js  c++  java
  • hdu 1728 逃离迷宫 BFS加优先队列 DFS()

    http://acm.hdu.edu.cn/showproblem.php?pid=1728

      题意就是能否在规定的转弯次数内从起点走到终点。刚走时那步方向不算。

      只会bfs(),但想到这题需要记录转弯次数,所以就想在建立的节点内部添加一个变量记录本次走的方向,然后和上次走的方向比较,不同就增加转弯次数。就这样,按照bfs一层一层扩展,为了将转弯次数少的先扩展,就想到采用优先队列。但是按照这种思路写出来的代码WA。

      后来看到网上有人倒着记录最小转弯次数(blog),也是采用的优先队列。虽然不知道作者为什么要倒着来,但我尝试这用这种写法正着来,这样也能过。

      参考代码:

     1 #include<iostream>
     2 #include<cstdio>
     3 #include<queue>
     4 #include<cstring>
     5 using namespace std;
     6 struct pos
     7 {
     8     int x, y,ori;
     9 };
    10 pos dir[4] = { {1,0,1},{0,1,2},{-1,0,3},{0,-1,4} };//四个方向偏移数组,第三维是代表这个方向的。
    11 struct Node
    12 {
    13     int x, y, cnt,dir;//cnt记录转弯次数
    14     bool operator < (const Node& rhs)const { //由于要是cnt小的先出队列,所以重载<
    15         return cnt > rhs.cnt;
    16     }
    17 };
    18 priority_queue<Node> que;
    19 int k, m, n, sx, sy, ex, ey;
    20 bool flag;
    21 int ans[105][105];//记录起点到能到达每个点时的最小转弯次数。
    22 char map[105][105];
    23 char s[105];
    24 
    25 bool in(int a, int b)
    26 {
    27     if (a >= 1 && a <= m&&b >= 1 && b <= n&&map[a][b] == '.') return true;
    28     return false;
    29 }
    30 
    31 void BFS()
    32 {
    33     while (!que.empty())
    34     {
    35         Node u, v;
    36         u = que.top(); que.pop();
    37 
    38         if (u.cnt > k) continue;//超过最大转弯次数就不用管了。
    39 
    40         for (int i = 0; i < 4; i++)
    41         {
    42             v.x = u.x + dir[i].x;
    43             v.y = u.y + dir[i].y;
    44             v.cnt = u.cnt;
    45             if (in(v.x, v.y))
    46             {
    47                 v.dir = dir[i].ori;//现在结点的方向是dir[i].ori
    48                 if (u.dir != -1 && v.dir != u.dir) {
    49                     v.cnt = u.cnt + 1;
    50                 }
    51                 if (ans[v.x][v.y] >=v.cnt) {//这里一定要有等号!
    52                     ans[v.x][v.y] = v.cnt;
    53                     que.push(v);
    54                 }
    55             }
    56         }
    57     }
    58     if (ans[ex][ey] <= k) flag = true;
    59 }
    60 
    61 int main()
    62 {
    63     int T;
    64     scanf("%d", &T);
    65     while (T--)
    66     {
    67         scanf("%d%d", &m, &n);
    68         for (int i = 1; i <= m; i++)
    69         {
    70             scanf("%s", s);
    71             for (int j = 0; j < n; j++)
    72             {
    73                 map[i][j + 1] = s[j];
    74                 ans[i][j + 1] = 1e8;
    75             }
    76         }
    77         scanf("%d%d%d%d%d", &k, &sy, &sx, &ey, &ex);
    78         flag = false;
    79         while (!que.empty()) que.pop();
    80         Node node;
    81         node.x = sx, node.y = sy;
    82         node.dir = -1, node.cnt = 0;
    83         que.push(node);
    84         BFS();
    85         if (flag) printf("yes
    ");
    86         else printf("no
    ");
    87     }
    88 }
    View Code 1

      

      我就是按照原作者的思路照猫画虎的正着写了一下。其实之前网上有人说bfs()优先队列写会错,我很疑惑为什么不行,自己写的的确过不了。现在想想也许可能是因为我之前扩展结点后设置了访问数组,访问过的就不再访问了。而上面代码的想法是用ans数组更新答案。并且让能更新的结点入队列!这样可能能保证只要能更新答案一个结点可以走多次。就像有人说的以前都是求最小步数,结点最多走一次,但求最小转弯数时就不一样了。不知道想法对不对>_<.

      网上大部分bfs()的办法都是到一个结点一直走到头。(blog1  blog2 )这个想法的确很好。

      参考代码:

     1 #include<iostream>
     2 #include<cstdio>
     3 #include<cstring>
     4 #include<algorithm>
     5 #include<queue>
     6 using namespace std;
     7 struct pos
     8 {
     9     int x, y;
    10 };
    11 pos dir[4] = { { 1,0 },{ 0,1 },{ -1,0 },{ 0,-1 } };
    12 struct Node
    13 {
    14     int x, y, cnt;
    15 };
    16 queue<Node> que;
    17 int vis[105][105];
    18 char map[105][105];
    19 char tmps[105];
    20 int m, n, sx, sy, ex, ey, k;
    21 
    22 bool in(int a, int b)
    23 {
    24     if (a >= 1 && a <= m&&b >= 1 && b <= n&&map[a][b] == '.') return true;
    25     return false;
    26 }
    27 
    28 int bfs()
    29 {
    30     while (!que.empty())
    31     {
    32         Node u;
    33         u = que.front(); que.pop();
    34 
    35         if (u.x == ex&&u.y == ey&&u.cnt <= k) return 1;
    36 
    37         Node v;
    38         v.cnt = u.cnt + 1;////因为前面搜完了一个方向,就肯定会拐弯,所以要+1,也因此起点的cnt初始化为-1;  
    39         for (int i = 0; i<4; i++)
    40         {
    41             v.x = u.x + dir[i].x;
    42             v.y = u.y + dir[i].y;
    43             while (in(v.x, v.y))
    44             {
    45                 if (!vis[v.x][v.y])
    46                 {
    47                     que.push(v);
    48                     vis[v.x][v.y] = 1;
    49                 }
    50                 v.x += dir[i].x;
    51                 v.y += dir[i].y;
    52             }
    53         }
    54     }
    55     return -1;
    56 }
    57 
    58 int main()
    59 {
    60     int t;
    61     scanf("%d", &t);
    62     while (t--)
    63     {
    64         memset(vis, 0, sizeof(vis));
    65         scanf("%d%d", &m, &n);
    66         for (int i = 1; i <= m; i++)
    67         {
    68             scanf("%s", tmps);
    69             for (int j = 0; j<n; j++)
    70             {
    71                 map[i][j + 1] = tmps[j];
    72                 vis[i][j + 1] = 0;
    73             }
    74         }
    75         scanf("%d%d%d%d%d", &k, &sy, &sx, &ey, &ex);
    76 
    77         while (!que.empty()) que.pop();
    78         Node u;
    79         u.x = sx, u.y = sy, u.cnt = -1;
    80         vis[u.x][u.y] = 1;
    81         que.push(u);
    82 
    83         int ans = -1;
    84         ans = bfs();
    85         if (ans >= 0)        printf("yes
    ");
    86         else        printf("no
    ");
    87     }
    88     return 0;
    89 }
    View Code 2

      最后就是dfs()解法。我本来看这道题没有深搜思路的,但觉得只要是搜索题,基本上两种方法都应该能做。就大概看了一下深搜解法。

      参考代码:

    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    #include<queue>
    using namespace std;
    struct pos
    {
        int x, y,ori;
    };
    pos dir[4] = { { 1,0,1 },{ 0,1,2 },{ -1,0,3 },{ 0,-1,4 } };//同bfs();
    int ans[105][105];
    char map[105][105];
    char tmps[105];
    bool flag;
    int m, n, sx, sy, ex, ey, k;
    
    bool in(int a, int b)
    {
        if (a >= 1 && a <= m&&b >= 1 && b <= n&&map[a][b] == '.') return true;
        return false;
    }
    
    void dfs(int x, int y, int cnt, int direct)//搜索的坐标、转弯次数、方向
    {
        if (x == ex&&y == ey&&cnt <= k) {
            flag = true;
            return;
        }
    
        for (int i = 0; i < 4; i++) {
            int newx = x + dir[i].x;
            int newy = y + dir[i].y;
            if (in(newx, newy))
            {
                if (direct == -1 || direct == dir[i].ori)
                {
                    ans[newx][newy] = cnt;
                    dfs(newx, newy, cnt, dir[i].ori);
                    if (flag) return;
                }
                else if(cnt<k&&ans[newx][newy]>cnt)
                {
                    ans[newx][newy] = cnt + 1;
                    dfs(newx, newy, cnt + 1, dir[i].ori);
                    if (flag) return;
                }
            }
        }
    
    }
    
    int main()
    {
        int t;
        scanf("%d", &t);
        while (t--)
        {
            scanf("%d%d", &m, &n);
            for (int i = 1; i <= m; i++)
            {
                scanf("%s", tmps);
                for (int j = 0; j<n; j++)
                {
                    map[i][j + 1] = tmps[j];
                    ans[i][j + 1] = 1e8;
                }
            }
            scanf("%d%d%d%d%d", &k, &sy, &sx, &ey, &ex);
            flag = false;
            dfs(sx, sy, 0, -1);//开始时方向为设为-1
            if (flag) printf("yes
    ");
            else printf("no
    ");
        }
        return 0;
    }
    View Code 3
  • 相关阅读:
    Python机器学习笔记:使用sklearn做特征工程和数据挖掘
    Python numpy中矩阵的用法总结
    Python机器学习笔记:K-近邻(KNN)算法
    Python机器学习笔记:Logistic Regression
    python机器学习笔记:ID3决策树算法实战
    Mysql 多表查询详解
    JavaScript cookie操作实现点赞功能
    js操作cookie
    【IntelliJ IDEA】idea上提交代码到GitHub,已经提交了 但是GitHub上却没有的解决办法
    Mybatis分页插件PageHelper的配置和使用方法
  • 原文地址:https://www.cnblogs.com/zxhyxiao/p/7211617.html
Copyright © 2011-2022 走看看