P1135
广度优先搜索易解的问题有如下的特点:
- 最短为最优
- 每个节点处的规则都唯一确定(不管各个节点的规则是否都相同),保证了单节点只扩展一次。
这个题就能很典型地体现第二点。
分析
这个题目走到每一个节点的时候,上下移动的规则都是相同的,所以扩展一次就不用再次扩展了,采用广度搜索的标准模板即可解。
另外
- 如果每个节点处的规则由深度而确定,那么则应使用深度优先搜索。因为广搜时要记录每一层不同的操作数量和操作规则。实在困难。
- 如果中途还能停的话,应该使用广搜(同时不pop,看起来也就不像是典型的广搜了),但是其复杂度会动态增大。
代码
一个典型的广搜问题,不要被这个不同节点的不同规则而搞乱掉了,毕竟每一节点(在题目中具体为楼层,不是搜索的层)都是一个确定的规则,随意扩展完后去除掉即可。复杂度是线性的。
#include <bits/stdc++.h>
using namespace std;
struct s
{
int f, n;
s(int _f, int _n) : f(_f), n(_n) { }
};
int k[205], vis[205];
int main()
{
queue<s> q;
int N, a, b;
cin >> N >> a >> b;
for (int i = 1; i <= N; i++)
cin >> k[i];
q.push(s(a, 0)); vis[a] = 1;
int tf, tn;
while (!q.empty())
{
tf = q.front().f, tn = q.front().n; q.pop();
if (tf == b) break;
int t1 = tf + k[tf], t2 = tf - k[tf];
if (t1 <= N && !vis[t1])
q.push(s(t1, tn+1)), vis[t1] = 1;
if (t2 >= 1 && !vis[t2])
q.push(s(t2, tn+1)), vis[t2] = 1;
}
if (tf == b) cout << tn;
else cout << "-1";
}