KIDx 的解题报告
HDU 1728 逃离迷宫 http://acm.hdu.edu.cn/showproblem.php?pid=1728
对于代码31行,为什么等于不能随便剪掉
如果剪掉就会出现下图结果:
【假如转弯数k=1,起点终点如图】
那么如果你的代码是优先向右搜索就会出错
红色的线是先搜的,由于最多转一次弯,所以不合题意;
蓝色是后搜的,因为遇到转弯数相等所以不往下走了了,但是继续走是可以满足题意输出"yes"的
![](http://dl.iteye.com/upload/attachment/584807/33c0d028-3930-3930-a467-be9b467fe128.jpg)
深搜:
融合深搜思想的广搜【单方向优先扩展】
HDU 1072 Nightmare http://acm.hdu.edu.cn/showproblem.php?pid=1072
深搜
广搜
HDU 1728 逃离迷宫 http://acm.hdu.edu.cn/showproblem.php?pid=1728
对于代码31行,为什么等于不能随便剪掉
如果剪掉就会出现下图结果:
【假如转弯数k=1,起点终点如图】
那么如果你的代码是优先向右搜索就会出错
红色的线是先搜的,由于最多转一次弯,所以不合题意;
蓝色是后搜的,因为遇到转弯数相等所以不往下走了了,但是继续走是可以满足题意输出"yes"的
![](http://dl.iteye.com/upload/attachment/584807/33c0d028-3930-3930-a467-be9b467fe128.jpg)
深搜:
![](http://dl.iteye.com/upload/attachment/598282/50265dc9-b988-3e96-92c1-3fe6c5a34df0.png)
- #include <iostream>
- using namespace std;
- #define inf 0x3fffffff
- #define M 105
- //1、wan用于转弯数剪枝;2、step用于步数剪枝,就不用vis标记访问了
- int r, c, ex, ey, k, wan[M][M];
- char map[M][M];
- int x_move[4] = {-1, 0, 1, 0};
- int y_move[4] = {0, 1, 0, -1};
- bool flag;
- void dfs (int x, int y, int dir) //dir为当前方向
- {
- if (x == ex && y == ey)
- {
- if (wan[x][y] <= k)
- flag = true;
- return ;
- }
- if (wan[x][y] > k) //转弯数超过k不用往下走了
- return ;
- //x !=ex && y != ey 说明必须至少再转一次弯,但是已经不能再转了
- if (wan[x][y] == k && x !=ex && y != ey)
- return ;
- for (int i = 0; i < 4; i++)
- {
- int tx = x + x_move[i];
- int ty = y + y_move[i];
- if (tx < 0 || tx >= r || ty < 0 || ty >= c)
- continue;
- //转弯数相等不可剪掉,所以是wan[tx][ty] < wan[x][y]而不是wan[tx][ty] <= wan[x][y]
- if (map[tx][ty] == '*' || wan[tx][ty] < wan[x][y]) //转弯数剪枝
- continue;
- if (dir != -1 && i != dir && wan[tx][ty] < wan[x][y] + 1) //转弯数剪枝
- continue;
- wan[tx][ty] = wan[x][y];
- if (dir != -1 && i != dir)
- wan[tx][ty]++; //如果方向变了转弯+1
- dfs (tx, ty, i);
- if (flag)
- return ;
- }
- }
- int main()
- {
- int t, i, j, sx, sy; //sx, sy是起点
- scanf ("%d", &t);
- while (t--)
- {
- scanf ("%d%d", &r, &c);
- for (i = 0; i < r; i++)
- scanf ("%s", map[i]);
- scanf ("%d%d%d%d%d", &k, &sy, &sx, &ey, &ex);
- sx--, sy--, ex--, ey--; //我从0开始编号,而题目是从1开始
- for (i = 0; i < r; i++)
- for (j = 0; j < c; j++)
- wan[i][j] = inf; //初始化转弯数和步数为无穷大
- wan[sx][sy] = 0; //到达起点的转弯数
- flag = false;
- dfs (sx, sy, -1); //一开始可以走任意方向,所以设方向为-1
- if (flag)
- puts ("yes");
- else puts ("no");
- }
- return 0;
- }
融合深搜思想的广搜【单方向优先扩展】
![](http://dl.iteye.com/upload/attachment/591190/710962f4-b251-3f88-972c-4b25f21054f3.png)
- #include <iostream>
- #include <queue>
- using namespace std;
- #define inf 0x3fffffff
- #define M 105
- int r, c, sx, sy, ex, ey, wan[M][M], t, k;
- char map[M][M];
- int x_move[4] = {-1, 0, 1, 0};
- int y_move[4] = {0, 1, 0, -1};
- struct pos{
- int x, y;
- };
- void bfs ()
- {
- int i, j;
- for (i = 0; i < r; i++)
- for (j = 0; j < c; j++)
- wan[i][j] = inf;
- pos ft, tp;
- ft.x = sx, ft.y = sy;
- wan[ft.x][ft.y] = -1;
- queue<pos> q;
- q.push (ft);
- while (!q.empty())
- {
- ft = q.front();
- q.pop();
- if (ft.x == ex && ft.y == ey && wan[ft.x][ft.y] <= k)
- {
- puts ("yes");
- return ;
- }
- for (i = 0; i < 4; i++)
- {
- tp.x = ft.x + x_move[i];
- tp.y = ft.y + y_move[i];
- while (!(tp.x < 0 || tp.y < 0 || tp.x >= r || tp.y >= c))
- {
- if (map[tp.x][tp.y] == '*')
- break;
- if (wan[tp.x][tp.y] < wan[ft.x][ft.y] + 1)
- break;
- wan[tp.x][tp.y] = wan[ft.x][ft.y] + 1;
- if (wan[tp.x][tp.y] > k)
- break;
- if (wan[tp.x][tp.y] == k && tp.x != ex && tp.y != ey)
- break;
- q.push (tp);
- tp.x += x_move[i];
- tp.y += y_move[i]; //单方向优先扩展
- }
- }
- }
- puts ("no");
- }
- int main()
- {
- int t, i;
- scanf ("%d", &t);
- while (t--)
- {
- scanf ("%d%d", &r, &c);
- for (i = 0; i < r; i++)
- scanf ("%s", map[i]);
- scanf ("%d%d%d%d%d", &k, &sy, &sx, &ey, &ex);
- sx--, sy--, ex--, ey--;
- bfs ();
- }
- return 0;
- }
HDU 1072 Nightmare http://acm.hdu.edu.cn/showproblem.php?pid=1072
深搜
- #include <iostream>
- using namespace std;
- #define inf 0x3fffffff
- #define M 10
- //step[i][j]表示从起点到ij需要的最小步数,T[i][j]表示走到ij诈弹还剩下的时间
- int r, c, mins;
- int map[M][M], step[M][M], T[M][M];
- int x_move[4] = {-1, 0, 1, 0};
- int y_move[4] = {0, 1, 0, -1};
- void dfs (int x, int y)
- {
- if (T[x][y] <= 0) //炸死了
- return ;
- if (map[x][y] == 3)
- {
- if (step[x][y] < mins)
- mins = step[x][y];
- return ;
- }
- for (int i = 0; i < 4; i++)
- {
- int tx = x + x_move[i];
- int ty = y + y_move[i];
- if (tx < 0 || tx >= r || ty < 0 || ty >= c)
- continue;
- if (map[tx][ty] == 0 ||
- step[tx][ty] <= step[x][y] + 1 && T[tx][ty] >= T[x][y] - 1)
- continue; //已访问过,而且如果走下去诈弹时间没变甚至变小,那还不如不走呢
- step[tx][ty] = step[x][y] + 1;
- T[tx][ty] = T[x][y] - 1;
- if (map[tx][ty] == 4 && T[tx][ty] > 0)
- T[tx][ty] = 6;
- //将诈弹时间置为6,按照题意走到txty必须诈弹还有剩余时间,否则还是要爆
- dfs (tx, ty);
- }
- }
- int main()
- {
- int t, i, j, sx, sy;
- scanf ("%d", &t);
- while (t--)
- {
- scanf ("%d %d", &r, &c);
- for (i = 0; i < r; i++)
- {
- for (j = 0; j < c; j++)
- {
- scanf ("%d", map[i]+j);
- if (map[i][j] == 2)
- sx = i, sy = j;
- step[i][j] = inf; //初始化步数为无穷大
- }
- }
- step[sx][sy] = 0; //到起点的最小步数是0
- memset (T, 0, sizeof(T)); //初始化诈弹剩余时间为0
- T[sx][sy] = 6; //起点的诈弹初始时间为6
- mins = inf;
- dfs (sx, sy);
- if (mins == inf)
- puts ("-1");
- else printf ("%d\n", mins);
- }
- return 0;
- }
广搜
- #include <iostream>
- #include <queue>
- using namespace std;
- #define inf 0x3fffffff
- #define M 10
- int sx, sy, step[M][M], T[M][M], r, c;
- int x_move[4] = {-1, 0, 1, 0};
- int y_move[4] = {0, 1, 0, -1};
- int map[M][M];
- struct pos{
- int x, y;
- };
- void bfs ()
- {
- int i, j;
- for (i = 0; i < r; i++)
- for (j = 0; j < c; j++)
- step[i][j] = inf, T[i][j] = 0;
- pos ft, tp;
- ft.x = sx, ft.y = sy;
- step[ft.x][ft.y] = 0;
- T[ft.x][ft.y] = 6;
- queue <pos> q;
- q.push (ft);
- while (!q.empty())
- {
- ft = q.front();
- q.pop();
- if (map[ft.x][ft.y] == 3 && T[ft.x][ft.y] > 0)
- {
- printf ("%d\n", step[ft.x][ft.y]);
- return ;
- }
- for (i = 0; i < 4; i++)
- {
- tp.x = ft.x + x_move[i];
- tp.y = ft.y + y_move[i];
- if (tp.x < 0 || tp.y < 0 || tp.x >= r || tp.y >= c)
- continue;
- if (map[tp.x][tp.y] == 0)
- continue;
- if (step[tp.x][tp.y] <= step[ft.x][ft.y] + 1 &&
- T[tp.x][tp.y] >= T[ft.x][ft.y] - 1)
- continue;
- step[tp.x][tp.y] = step[ft.x][ft.y] + 1;
- T[tp.x][tp.y] = T[ft.x][ft.y] - 1;
- if (T[tp.x][tp.y] <= 0)
- continue;
- if (map[tp.x][tp.y] == 4)
- T[tp.x][tp.y] = 6;
- q.push (tp);
- }
- }
- puts ("-1");
- }
- int main()
- {
- int t, i, j;
- scanf ("%d", &t);
- while (t--)
- {
- scanf ("%d%d", &r, &c);
- for (i = 0; i < r; i++)
- {
- for (j = 0; j < c; j++)
- {
- scanf ("%d", map[i]+j);
- if (map[i][j] == 2)
- sx = i, sy = j;
- }
- }
- bfs ();
- }
- return 0;
- }