bfs——鸣人与佐助
http://bailian.openjudge.cn/practice/4115/
发现了没有这题包括之前的题目在广搜里面都涉及到了状态这个词。而状态里面的变量是会随着广搜的过程和题目的限制发生相应的变化的。比如上一题的迷宫问题状态中就有x与y坐标和父节点这几个参数。这一题由于多了一个查克拉的限制所以在状态中加上查克拉。
题解:
这道题用BFS来做。
1、由于每一层加的时间是一样的,所以最先遇到佐助的路径一定是最优路径,所以遇到佐助就要停下来,就出答案了。
2、然而这道题有烦人的查克拉问题,可能最短路会由于全是守卫,所以查克拉不够用,必须要绕路才能走过去,所以不能按照普通的BFS一样用一个vis数组,这道题里面的每个节点的数值可能是要更新的。
3、然而肯定要有个东西作为不能继续进行下去的剪枝,不然会一直更新原来的节点,程序必然会TLE,所以,用一个maxk数组来剪枝,maxk数组存储如果要到这个节点所剩查克拉的最多是多少,如果后面又扩展出这个节点,那时间一定会大于等于上次扩展出这个节点,这时候,如果此时的所剩查克拉数还少于上一次所剩,那么肯定不是最优解,剪枝。
4、由于各个节点的值要更新,而且更新是否正确根据能否走到为判断标准,所以不如把需要更新的值写入结构体,压入队列时就一并算是更新了。
解题思路来自:https://blog.csdn.net/Ema1997/article/details/52108717
这一段代码还是质量很高的后面可以自己写一写。还有上面还是用到了剪枝的思维
#include <iostream> #include <cstdio> #include <string> #include <algorithm> #include <cstring> #include <cmath> #include <vector> #include <map> #include <set> #include <queue> using namespace std; struct point{ int x, y, k, t;//t存储走完这一步还剩多少查克拉 point(int xx, int yy, int kk, int tt) : x(xx), y(yy), k(kk), t(tt) {} }; const int maxn = 205; const int INF = 1 << 30; char maze[maxn][maxn]; int answer, dir[4][2] = {{1, 0}, {-1, 0}, {0, 1}, {0, -1}}; int maxk[maxn][maxn];//到达这个格子还剩查克拉最大值 int m, n, t; queue<point> q; void BFS() { while (!q.empty()) { point now = q.front(); q.pop(); if (maze[now.x][now.y] == '+') { answer = now.t; return; } else { for (int i = 0; i < 4; i++) { int tempx = now.x + dir[i][0]; int tempy = now.y + dir[i][1]; if (tempx < 0 || tempx >= m || tempy < 0 || tempy >= n || maxk[tempx][tempy] >= now.k)
continue;//边界一定要判断清楚 if (maze[tempx][tempy] == '#') { if (now.k > 0) { q.push(point(tempx, tempy, now.k - 1, now.t + 1)); maxk[tempx][tempy] = now.k; } } else { q.push(point(tempx, tempy, now.k, now.t + 1)); maxk[tempx][tempy] = now.k; } } } } } int main() { #ifndef ONLINE_JUDGE freopen ("in.txt", "r", stdin); #endif // ONLINE_JUDGE cin >> m >> n >> t; for (int i = 0; i < m; i++) { for (int j = 0; j < n; j++) { cin >> maze[i][j]; maxk[i][j] = -1; if (maze[i][j] == '@') { q.push(point(i, j, t, 0)); maxk[i][j] = t; } } } answer = INF; BFS (); if (answer == INF) { cout << -1 << endl; } else { cout << answer << endl; } return 0; }
我发现我中间最优剪枝还是很不熟,甚至是没有理解。我突然发现一件事,这个代码居然没有一个三维数组来判重。