• HDU 1728 逃离迷宫


    这道题做的我想哭啊。。WA了将近十次了吧

    一开始我用数组模拟的队列,后来和老大代码对拍,感觉改的是基本都一模一样了,还是WA

    实在没有办法了,改用queue了

    题目里的x是列y是行,和代码里的反过来的,要注意!

    题目里面说在起点的时候无论朝哪个方向走都不算一次转弯,所以我们将方向和转弯次数都赋值为-1,这样就不用特殊处理了

    入队条件,拓展后的转弯次数小于或等于vis数组中记录的最小转弯次数即可入队

    输出结果,不要一搜到终点便急着输出,应为可能后面再一次搜到终点的时候转弯次数小于k

    因此可以遍历完以后再输出,或者输出yes的时候加一个限制条件:转弯次数小于等于k

    两种处理方法,第二种更快一点

    这里先把数组WA掉的代码贴上,留着以后再找错。

     1 //#define LOCAL
     2 #include <iostream>
     3 #include <cstdio>
     4 #include <cstring>
     5 using namespace std;
     6 
     7 struct Point
     8 {
     9     int x, y;
    10     int di, times;
    11 }qu[20000 + 10];
    12 
    13 const int MAX = 200;
    14 char map[105][105];
    15 int dir[4][2] = {{1, 0}, {-1, 0}, {0, 1}, {0, -1}};
    16 int row, col, vis[105][105];
    17 int sx, sy, ex, ey, k;
    18 int head, tail;
    19 
    20 bool islegal(int x, int y)
    21 {
    22     if(x>=0 && x<row && y>=0 && y<col && map[x][y]=='.')
    23         return true;
    24     return false;
    25 }
    26 
    27 void BFS(void)
    28 {
    29     head = 0, tail = 1;
    30     vis[sx][sy] = 0;
    31     qu[0].x = sx, qu[0].y = sy;
    32     qu[0].di = -1, qu[0].times = -1;
    33     while(head < tail)
    34     {
    35         //if(qu[head].x==ex && qu[head].y==ey)
    36             //{printf("yes
    ");    return;}
    37         for(int i = 0; i < 4; ++i)
    38         {
    39             int temp;
    40             int xx = qu[head].x + dir[i][0];
    41             int yy = qu[head].y + dir[i][1];
    42             if(!islegal(xx, yy))    continue;
    43             if(i != qu[head].di)
    44                 temp = qu[head].times + 1;
    45             else
    46                 temp = qu[head].times;
    47             if(temp > k)    continue;
    48             if(temp <= vis[xx][yy])
    49             {
    50                 vis[xx][yy] = temp;
    51                 qu[tail].x = xx, qu[tail].y = yy;
    52                 qu[tail].di = i;
    53                 qu[tail++].times = temp;
    54             }
    55         }
    56         ++head;
    57     }
    58     if(vis[ex][ey] <= k)
    59         printf("yes
    ");
    60     else
    61         printf("no
    ");
    62 }
    63 
    64 int main(void)
    65 {
    66     #ifdef LOCAL
    67         freopen("1728in.txt", "r", stdin);
    68     #endif
    69 
    70     int T;
    71     scanf("%d", &T);
    72     while(T--)
    73     {
    74         scanf("%d%d", &row, &col);
    75         getchar();
    76         for(int i = 0; i < row; ++i)
    77         {
    78             for(int j = 0; j < col; ++j)
    79             {
    80                 scanf("%c", &map[i][j]);
    81                 vis[i][j] = MAX;
    82             }
    83             getchar();
    84         }
    85         scanf("%d%d%d%d%d", &k, &sy, &sx, &ey, &ex);
    86         --sx, --sy, --ex, --ey;
    87         BFS();
    88     }
    89     return 0;
    90 }
    代码君

    queue的AC代码:

     1 //#define LOCAL
     2 #include <iostream>
     3 #include <cstdio>
     4 #include <cstring>
     5 #include <queue>
     6 using namespace std;
     7 
     8 struct Point
     9 {
    10     int x, y;
    11     int di, times;
    12 }qu[20000 + 10];
    13 
    14 const int MAX = 200;
    15 char map[105][105];
    16 int dir[4][2] = {{1, 0}, {-1, 0}, {0, 1}, {0, -1}};
    17 int row, col, vis[105][105];
    18 int sx, sy, ex, ey, k;
    19 
    20 bool islegal(int x, int y)
    21 {
    22     return(x>=0 && x<row && y>=0 && y<col && map[x][y]=='.');
    23 }
    24 
    25 void BFS(void)
    26 {
    27     queue<Point> qu;
    28     vis[sx][sy] = 0;
    29     Point cur;
    30     cur.x = sx, cur.y = sy;
    31     cur.di = cur.times = -1;
    32     qu.push(cur);
    33     while(!qu.empty())
    34     {
    35         cur = qu.front();
    36         qu.pop();
    37         if(cur.x==ex&&cur.y==ey&&cur.times<=k)
    38         {
    39             printf("yes
    ");
    40             return;
    41         }
    42         for(int i = 0; i < 4; ++i)
    43         {
    44             Point next = cur;
    45             next.x += dir[i][0];
    46             next.y += dir[i][1];
    47             if(!islegal(next.x, next.y))    continue;
    48             if(i != cur.di)
    49             {
    50                 next.di = i;
    51                 ++next.times;
    52             }
    53             if(next.times > k)    continue;
    54             if(next.times <= vis[next.x][next.y])
    55             {
    56                 vis[next.x][next.y] = next.times;
    57                 qu.push(next);
    58             }
    59         }
    60     }
    61     printf("no
    ");
    62 }
    63 
    64 int main(void)
    65 {
    66     #ifdef LOCAL
    67         freopen("1728in.txt", "r", stdin);
    68     #endif
    69 
    70     int T;
    71     scanf("%d", &T);
    72     while(T--)
    73     {
    74         scanf("%d%d", &row, &col);
    75         getchar();
    76         for(int i = 0; i < row; ++i)
    77         {
    78             for(int j = 0; j < col; ++j)
    79             {
    80                 scanf("%c", &map[i][j]);
    81                 vis[i][j] = MAX;
    82             }
    83             getchar();
    84         }
    85         scanf("%d%d%d%d%d", &k, &sy, &sx, &ey, &ex);
    86         --sx, --sy, --ex, --ey;
    87         BFS();
    88     }
    89     return 0;
    90 }
    代码君

    对比了一下别人的代码,才知道自己写的代码有多么挫。。

    http://972169909-qq-com.iteye.com/blog/1244218

    这里讲了两种方法,因为题目只是问能不能在转k个弯之内到达,而不是转的最小的弯,所以DFS也是能做的。30MS多点

     1 //#define LOCAL
     2 #include <iostream>
     3 #include <cstdio>
     4 #include <cstring>
     5 using namespace std;
     6 
     7 const int MAX = 200;
     8 char map[105][105];
     9 int dir[4][2] = {{1, 0}, {-1, 0}, {0, 1}, {0, -1}};
    10 int row, col, vis[105][105];
    11 int sx, sy, ex, ey, k;
    12 bool flag; 
    13 
    14 bool islegal(int x, int y)
    15 {
    16     return(x>=0 && x<row && y>=0 && y<col && map[x][y]=='.');
    17 }
    18 
    19 void DFS(int x, int y, int di)
    20 {
    21     if(x==ex && y==ey && vis[ex][ey]<=k)
    22         {flag = true;   return;}
    23     if(vis[x][y] > k)
    24         return;
    25     if(x!=ex && y!=ey && vis[x][y]==k)
    26         return;
    27     for(int i = 0; i < 4; ++i)
    28     {
    29         int tx = x + dir[i][0];
    30         int ty = y + dir[i][1];
    31         if(!islegal(tx, ty))
    32             continue;
    33         if(vis[tx][ty] < vis[x][y])
    34             continue;
    35         if(i!=di && vis[tx][ty] < vis[x][y]+1)
    36             continue;
    37         vis[tx][ty] = vis[x][y];
    38         if(i != di)
    39             ++vis[tx][ty];
    40         DFS(tx, ty, i);
    41         if(flag)
    42             return;
    43     }
    44 }
    45 
    46 int main(void)
    47 {
    48     #ifdef LOCAL
    49         freopen("1728in.txt", "r", stdin);
    50     #endif
    51 
    52     int T;
    53     scanf("%d", &T);
    54     while(T--)
    55     {
    56         scanf("%d%d", &row, &col);
    57         getchar();
    58         for(int i = 0; i < row; ++i)
    59         {
    60             for(int j = 0; j < col; ++j)
    61             {
    62                 scanf("%c", &map[i][j]);
    63                 vis[i][j] = MAX;
    64             }
    65             getchar();
    66         }
    67         scanf("%d%d%d%d%d", &k, &sy, &sx, &ey, &ex);
    68         --sx, --sy, --ex, --ey;
    69         vis[sx][sy] = -1;
    70         flag = false;
    71         DFS(sx, sy, -1);
    72         if(flag)    printf("yes
    ");
    73         else    printf("no
    ");
    74     }
    75     return 0;
    76 }
    代码君

    下面重头戏来了,解法永远都是只有更好没有最好。博主讲了一个单方向优先扩展的广搜

    把一般的广搜比作一个石子在起点激起一圈圈涟漪,单方向优先的就是向开车一样“横冲直撞”、直来直往

    因为我们是要找转弯次数最小的,因此这样的搜索方式应该也能较快的找到符合条件的路径,运行时间15MS

    感觉代码的有些小细节还没有理解透,等以后回过头来慢慢消化

     1 //#define LOCAL
     2 #include <iostream>
     3 #include <cstdio>
     4 #include <cstring>
     5 #include <queue>
     6 using namespace std;
     7 
     8 struct Point
     9 {
    10     int x, y;
    11 }cur, next;
    12 
    13 const int MAX = 200;
    14 char map[105][105];
    15 int dir[4][2] = {{1, 0}, {-1, 0}, {0, 1}, {0, -1}};
    16 int row, col, vis[105][105];
    17 int sx, sy, ex, ey, k;
    18 
    19 bool islegal(int x, int y)
    20 {
    21     return(x>=0 && x<row && y>=0 && y<col && map[x][y]=='.');
    22 }
    23 
    24 void BFS(void)
    25 {
    26     queue<Point> qu;
    27     vis[sx][sy] = -1;
    28     Point cur;
    29     cur.x = sx, cur.y = sy;
    30     qu.push(cur);
    31     while(!qu.empty())
    32     {
    33         cur = qu.front();
    34         qu.pop();
    35         if(cur.x==ex&&cur.y==ey&&vis[cur.x][cur.y]<=k)
    36         {
    37             printf("yes
    ");
    38             return;
    39         }
    40         for(int i = 0; i < 4; ++i)
    41         {
    42             next = cur;
    43             next.x += dir[i][0];
    44             next.y += dir[i][1];
    45             while(islegal(next.x, next.y))
    46             {
    47                 if(vis[next.x][next.y] < vis[cur.x][cur.y] + 1)
    48                     break;
    49                 vis[next.x][next.y] = vis[cur.x][cur.y] + 1;
    50                 if(vis[next.x][next.y] > k)
    51                     break;
    52                 if(vis[next.x][next.y] == k && next.x!=ex && next.y!=ey)
    53                     break;
    54                 qu.push(next);
    55                 next.x += dir[i][0];
    56                 next.y += dir[i][1];
    57             }
    58         }
    59     }
    60     printf("no
    ");
    61 }
    62 
    63 int main(void)
    64 {
    65     #ifdef LOCAL
    66         freopen("1728in.txt", "r", stdin);
    67     #endif
    68 
    69     int T;
    70     scanf("%d", &T);
    71     while(T--)
    72     {
    73         scanf("%d%d", &row, &col);
    74         getchar();
    75         for(int i = 0; i < row; ++i)
    76         {
    77             for(int j = 0; j < col; ++j)
    78             {
    79                 scanf("%c", &map[i][j]);
    80                 vis[i][j] = MAX;
    81             }
    82             getchar();
    83         }
    84         scanf("%d%d%d%d%d", &k, &sy, &sx, &ey, &ex);
    85         --sx, --sy, --ex, --ey;
    86         BFS();
    87     }
    88     return 0;
    89 }
    代码君
  • 相关阅读:
    160. Intersection of Two Linked Lists
    155. Min Stack
    TensorRT caffemodel serialize序列化
    141. Linked List Cycle
    异或运算的性质及应用
    136. Single Number
    【leeetcode】125-Valid Palindrome
    c++函数参数类型-引用、指针、值
    【linux基础】linux远程登录SSH
    【leetcode】122-Best Time to Buy and Sell Stock II
  • 原文地址:https://www.cnblogs.com/AOQNRMGYXLMV/p/3918065.html
Copyright © 2020-2023  润新知