HDU 1728 逃离迷宫 + HDU 1072 Nightmare(bfs+dfs)

来源:互联网 发布:js播放器进度条 编辑:程序博客网 时间:2024/06/06 00:54
KIDx 的解题报告
HDU 1728 逃离迷宫 http://acm.hdu.edu.cn/showproblem.php?pid=1728
对于代码31行,为什么等于不能随便剪掉
如果剪掉就会出现下图结果:
【假如转弯数k=1,起点终点如图】
那么如果你的代码是优先向右搜索就会出错
红色的线是先搜的,由于最多转一次弯,所以不合题意;
蓝色是后搜的,因为遇到转弯数相等所以不往下走了了,但是继续走是可以满足题意输出"yes"的


深搜:

C++代码  收藏代码
  1. #include <iostream>  
  2. using namespace std;  
  3. #define inf 0x3fffffff  
  4. #define M 105  
  5.     //1、wan用于转弯数剪枝;2、step用于步数剪枝,就不用vis标记访问了  
  6. int r, c, ex, ey, k, wan[M][M];  
  7. char map[M][M];  
  8. int x_move[4] = {-1, 0, 1, 0};  
  9. int y_move[4] = {0, 1, 0, -1};  
  10. bool flag;  
  11.   
  12. void dfs (int x, int y, int dir)    //dir为当前方向  
  13. {  
  14.     if (x == ex && y == ey)  
  15.     {  
  16.         if (wan[x][y] <= k)  
  17.             flag = true;  
  18.         return ;  
  19.     }  
  20.     if (wan[x][y] > k)   //转弯数超过k不用往下走了  
  21.         return ;  
  22.     //x !=ex && y != ey 说明必须至少再转一次弯,但是已经不能再转了  
  23.     if (wan[x][y] == k && x !=ex && y != ey)  
  24.         return ;  
  25.     for (int i = 0; i < 4; i++)  
  26.     {  
  27.         int tx = x + x_move[i];  
  28.         int ty = y + y_move[i];  
  29.         if (tx < 0 || tx >= r || ty < 0 || ty >= c)  
  30.             continue;  
  31. //转弯数相等不可剪掉,所以是wan[tx][ty] < wan[x][y]而不是wan[tx][ty] <= wan[x][y]  
  32.         if (map[tx][ty] == '*' || wan[tx][ty] < wan[x][y])   //转弯数剪枝  
  33.             continue;   
  34.         if (dir != -1 && i != dir && wan[tx][ty] < wan[x][y] + 1)    //转弯数剪枝  
  35.             continue;  
  36.         wan[tx][ty] = wan[x][y];  
  37.         if (dir != -1 && i != dir)  
  38.             wan[tx][ty]++;  //如果方向变了转弯+1  
  39.         dfs (tx, ty, i);  
  40.         if (flag)  
  41.             return ;  
  42.     }  
  43. }  
  44.   
  45. int main()  
  46. {  
  47.     int t, i, j, sx, sy;    //sx, sy是起点  
  48.     scanf ("%d", &t);  
  49.     while (t--)  
  50.     {  
  51.         scanf ("%d%d", &r, &c);  
  52.         for (i = 0; i < r; i++)  
  53.             scanf ("%s", map[i]);  
  54.         scanf ("%d%d%d%d%d", &k, &sy, &sx, &ey, &ex);  
  55.         sx--, sy--, ex--, ey--;     //我从0开始编号,而题目是从1开始  
  56.         for (i = 0; i < r; i++)  
  57.             for (j = 0; j < c; j++)  
  58.                 wan[i][j] = inf;    //初始化转弯数和步数为无穷大  
  59.         wan[sx][sy] = 0;    //到达起点的转弯数  
  60.         flag = false;  
  61.         dfs (sx, sy, -1);   //一开始可以走任意方向,所以设方向为-1  
  62.         if (flag)  
  63.             puts ("yes");  
  64.         else puts ("no");  
  65.     }  
  66.     return 0;  
  67. }  

融合深搜思想的广搜【单方向优先扩展】

C++代码  收藏代码
  1. #include <iostream>  
  2. #include <queue>  
  3. using namespace std;  
  4. #define inf 0x3fffffff  
  5. #define M 105  
  6.   
  7. int r, c, sx, sy, ex, ey, wan[M][M], t, k;  
  8. char map[M][M];  
  9. int x_move[4] = {-1, 0, 1, 0};  
  10. int y_move[4] = {0, 1, 0, -1};  
  11.   
  12. struct pos{  
  13.     int x, y;  
  14. };  
  15.   
  16. void bfs ()  
  17. {  
  18.     int i, j;  
  19.     for (i = 0; i < r; i++)  
  20.         for (j = 0; j < c; j++)  
  21.             wan[i][j] = inf;  
  22.     pos ft, tp;  
  23.     ft.x = sx, ft.y = sy;  
  24.     wan[ft.x][ft.y] = -1;  
  25.     queue<pos> q;  
  26.     q.push (ft);  
  27.     while (!q.empty())  
  28.     {  
  29.         ft = q.front();  
  30.         q.pop();  
  31.         if (ft.x == ex && ft.y == ey && wan[ft.x][ft.y] <= k)  
  32.         {  
  33.             puts ("yes");  
  34.             return ;  
  35.         }  
  36.         for (i = 0; i < 4; i++)  
  37.         {  
  38.             tp.x = ft.x + x_move[i];  
  39.             tp.y = ft.y + y_move[i];  
  40.             while (!(tp.x < 0 || tp.y < 0 || tp.x >= r || tp.y >= c))  
  41.             {  
  42.                 if (map[tp.x][tp.y] == '*')  
  43.                     break;  
  44.                 if (wan[tp.x][tp.y] < wan[ft.x][ft.y] + 1)  
  45.                     break;  
  46.                 wan[tp.x][tp.y] = wan[ft.x][ft.y] + 1;  
  47.                 if (wan[tp.x][tp.y] > k)  
  48.                     break;  
  49.                 if (wan[tp.x][tp.y] == k && tp.x != ex && tp.y != ey)  
  50.                     break;  
  51.                 q.push (tp);  
  52.                 tp.x += x_move[i];  
  53.                 tp.y += y_move[i];    //单方向优先扩展  
  54.             }  
  55.         }  
  56.     }  
  57.     puts ("no");  
  58. }  
  59.   
  60. int main()  
  61. {  
  62.     int t, i;  
  63.     scanf ("%d", &t);  
  64.     while (t--)  
  65.     {  
  66.         scanf ("%d%d", &r, &c);  
  67.         for (i = 0; i < r; i++)  
  68.             scanf ("%s", map[i]);  
  69.         scanf ("%d%d%d%d%d", &k, &sy, &sx, &ey, &ex);  
  70.         sx--, sy--, ex--, ey--;  
  71.         bfs ();  
  72.     }  
  73.     return 0;  
  74. }  


HDU 1072 Nightmare http://acm.hdu.edu.cn/showproblem.php?pid=1072
深搜

C++代码  收藏代码
  1. #include <iostream>  
  2. using namespace std;  
  3. #define inf 0x3fffffff  
  4. #define M 10  
  5.     //step[i][j]表示从起点到ij需要的最小步数,T[i][j]表示走到ij诈弹还剩下的时间  
  6. int r, c, mins;  
  7. int map[M][M], step[M][M], T[M][M];  
  8. int x_move[4] = {-1, 0, 1, 0};  
  9. int y_move[4] = {0, 1, 0, -1};  
  10.   
  11. void dfs (int x, int y)  
  12. {  
  13.     if (T[x][y] <= 0)    //炸死了  
  14.         return ;  
  15.     if (map[x][y] == 3)  
  16.     {  
  17.         if (step[x][y] < mins)  
  18.             mins = step[x][y];  
  19.         return ;  
  20.     }  
  21.     for (int i = 0; i < 4; i++)  
  22.     {  
  23.         int tx = x + x_move[i];  
  24.         int ty = y + y_move[i];  
  25.         if (tx < 0 || tx >= r || ty < 0 || ty >= c)  
  26.             continue;  
  27.         if (map[tx][ty] == 0 ||  
  28.         step[tx][ty] <= step[x][y] + 1 && T[tx][ty] >= T[x][y] - 1)  
  29.             continue;    //已访问过,而且如果走下去诈弹时间没变甚至变小,那还不如不走呢  
  30.         step[tx][ty] = step[x][y] + 1;  
  31.         T[tx][ty] = T[x][y] - 1;  
  32.         if (map[tx][ty] == 4 && T[tx][ty] > 0)  
  33.             T[tx][ty] = 6;  
  34.         //将诈弹时间置为6,按照题意走到txty必须诈弹还有剩余时间,否则还是要爆  
  35.         dfs (tx, ty);  
  36.     }  
  37. }  
  38.   
  39. int main()  
  40. {  
  41.     int t, i, j, sx, sy;  
  42.     scanf ("%d", &t);  
  43.     while (t--)  
  44.     {  
  45.         scanf ("%d %d", &r, &c);  
  46.         for (i = 0; i < r; i++)  
  47.         {  
  48.             for (j = 0; j < c; j++)  
  49.             {  
  50.                 scanf ("%d", map[i]+j);  
  51.                 if (map[i][j] == 2)  
  52.                     sx = i, sy = j;  
  53.                 step[i][j] = inf;   //初始化步数为无穷大  
  54.             }  
  55.         }  
  56.         step[sx][sy] = 0;           //到起点的最小步数是0  
  57.         memset (T, 0, sizeof(T));   //初始化诈弹剩余时间为0  
  58.         T[sx][sy] = 6;              //起点的诈弹初始时间为6  
  59.         mins = inf;  
  60.         dfs (sx, sy);  
  61.         if (mins == inf)  
  62.             puts ("-1");  
  63.         else printf ("%d\n", mins);  
  64.     }  
  65.     return 0;  
  66. }  

广搜
C++代码  收藏代码
  1. #include <iostream>  
  2. #include <queue>  
  3. using namespace std;  
  4. #define inf 0x3fffffff  
  5. #define M 10  
  6.   
  7. int sx, sy, step[M][M], T[M][M], r, c;  
  8. int x_move[4] = {-1, 0, 1, 0};  
  9. int y_move[4] = {0, 1, 0, -1};  
  10. int map[M][M];  
  11.   
  12. struct pos{  
  13.     int x, y;  
  14. };  
  15.   
  16. void bfs ()  
  17. {  
  18.     int i, j;  
  19.     for (i = 0; i < r; i++)  
  20.         for (j = 0; j < c; j++)  
  21.             step[i][j] = inf, T[i][j] = 0;  
  22.     pos ft, tp;  
  23.     ft.x = sx, ft.y = sy;  
  24.     step[ft.x][ft.y] = 0;  
  25.     T[ft.x][ft.y] = 6;  
  26.     queue <pos> q;  
  27.     q.push (ft);  
  28.     while (!q.empty())  
  29.     {  
  30.         ft = q.front();  
  31.         q.pop();  
  32.         if (map[ft.x][ft.y] == 3 && T[ft.x][ft.y] > 0)  
  33.         {  
  34.             printf ("%d\n", step[ft.x][ft.y]);  
  35.             return ;  
  36.         }  
  37.         for (i = 0; i < 4; i++)  
  38.         {  
  39.             tp.x = ft.x + x_move[i];  
  40.             tp.y = ft.y + y_move[i];  
  41.             if (tp.x < 0 || tp.y < 0 || tp.x >= r || tp.y >= c)  
  42.                 continue;  
  43.             if (map[tp.x][tp.y] == 0)  
  44.                 continue;  
  45.             if (step[tp.x][tp.y] <= step[ft.x][ft.y] + 1 &&   
  46.             T[tp.x][tp.y] >= T[ft.x][ft.y] - 1)  
  47.                 continue;  
  48.             step[tp.x][tp.y] = step[ft.x][ft.y] + 1;  
  49.             T[tp.x][tp.y] = T[ft.x][ft.y] - 1;  
  50.             if (T[tp.x][tp.y] <= 0)  
  51.                 continue;  
  52.             if (map[tp.x][tp.y] == 4)  
  53.                 T[tp.x][tp.y] = 6;  
  54.             q.push (tp);  
  55.         }  
  56.     }  
  57.     puts ("-1");  
  58. }  
  59.   
  60. int main()  
  61. {  
  62.     int t, i, j;  
  63.     scanf ("%d", &t);  
  64.     while (t--)  
  65.     {  
  66.         scanf ("%d%d", &r, &c);  
  67.         for (i = 0; i < r; i++)  
  68.         {  
  69.             for (j = 0; j < c; j++)  
  70.             {  
  71.                 scanf ("%d", map[i]+j);  
  72.                 if (map[i][j] == 2)  
  73.                     sx = i, sy = j;  
  74.             }  
  75.         }  
  76.         bfs ();  
  77.     }  
  78.     return 0;  
  79. }  
原创粉丝点击
热门问题 老师的惩罚 人脸识别 我在镇武司摸鱼那些年 重生之率土为王 我在大康的咸鱼生活 盘龙之生命进化 天生仙种 凡人之先天五行 春回大明朝 姑娘不必设防,我是瞎子 医保报销后认定工伤怎么办 结肠癌术后复查有息肉怎么办 无蒂息肉恶变要怎么办 贤者时间很长怎么办 鸡吃了酒米醉了怎么办 自填脂肪乳房脂肪液化怎么办 中国人在外国遇到危险怎么办 dnf刷图卡住了怎么办 dbf深渊怪卡住了怎么办 dnf86级没任务了怎么办 dnf二觉任务没了怎么办 脚趾甲变空向上翘怎么办 汽油车加了一点柴油怎么办 柴油车辆环保检测功率不足怎么办 加95加错一次92怎么办 新车95加错92油怎么办 加不到95号汽油怎么办 去新疆没95号油怎么办 黄龙300加了92怎么办 gla错加92号油 怎么办 95和98混加了怎么办 沥青车可以停在居民区怎么办 汽油进到眼睛了怎么办 汽油进了眼睛里怎么办 眼睛里面进了汽油怎么办 脱硫塔里的二氧化硫高怎么办 恐怖黎明铁匠选错怎么办 堡垒之夜草变色怎么办 火柴没有擦的了怎么办 乙醚倒进下水道了怎么办 乙醚和水不分层怎么办 乙醚闻多了头晕怎么办 爱乐维吃了便秘怎么办 刮完滑石粉墙面很软怎么办 被硫酸泼到皮肤怎么办 头磕了一下头晕怎么办 家里有事与工作不能请怎么办 撞了头头晕想吐怎么办 猫不小心摔一下怎么办 一氧化二氮中毒怎么办 电脑开机变慢了怎么办