链接——题目在这里!!!
题目背景
感谢 @yummy 提供的一些数据。
题目描述
呵呵,有一天我做了一个梦,梦见了一种很奇怪的电梯。大楼的每一层楼都可以停电梯,而且第 i 层楼(1≤i≤N)上有一个数字 Ki(0≤Ki≤N)。电梯只有四个按钮:开,关,上,下。上下的层数等于当前楼层上的那个数字。当然,如果不能满足要求,相应的按钮就会失灵。例如: 3,3,1,2,53,3,1,2,5 代表了 Ki(K1=3,K2=3,……),从 1 楼开始。在 1 楼,按“上”可以到 4楼,按“下”是不起作用的,因为没有 −2 楼。那么,从 A 楼到 B 楼至少要按几次按钮呢?
输入格式
共二行。
第一行为三个用空格隔开的正整数,表示N,A,B(1≤N≤200,1≤A,B≤N)。
第二行为 N 个用空格隔开的非负整数,表示 Ki。
输出格式
一行,即最少按键次数,若无法到达,则输出 -1
。
输入输出样例
输入 #1
5 1 5
3 3 1 2 5
输出 #1
3
说明/提示
对于 100%的数据,1≤N≤200,1≤A,B≤N,0≤Ki≤N。
本题共 16个测试点,前 15个每个测试点 6分,最后一个测试点 10分。
以下我们将按一次按钮视作当前时刻加 1。
对于一个点,我们明显只会关心更早到达这个点的时刻,而之后到达的我们都不关心,因为更晚到达的情况拓展出去的状态肯定是会更劣的。
所以我们希望更早地拓展时间最小的状态,以此来保证我到达某个点时的时间一定到达它的最短时间。
考虑到每个边的代价都是 1,那么我们可以果断使用 bfs 来解决这一问题。
首先,我们每次贪心地选择当前时间最小的点向外拓展,如果拓展到了没有到达过的点那么就更新这个点的答案,由于我们取的是当前时间最小的点,所以它拓展到的点一定是当前能拓展到的点中到达时刻最小的点,而且在它之后被拓展到的点的到达时间都不会比这个点小,也就是说到达时间小的点一定会更先被拓展,我们按照访问到的顺序把点存在队列里就行,每次取出队列的第一个拓展。
所以就这样直接 BFS 就行,这道题 DFS 或 BFS 均可,但是 BFS 相对更加好写(无需剪枝)。
BFS 广度优先搜索是使用队列(queue,先进先出)来实现,整个过程也可以看做一个倒立的树形:
最坏情况 O(n)。
#include
using namespace std;
#define M 200
int arr[M + 5], vis[M + 5] = { 0 };
void dfs(int i, int a, int n) {
if (vis[a] <= i) return;
vis[a] = i;
if (a - arr[a] >= 1) {
dfs(i + 1, a - arr[a], n);
}
if (a + arr[a] <= n) {
dfs(i + 1, a + arr[a], n);
}
return;
}
int main() {
int n, a, b;
cin >> n >> a >> b;
for (int i = 1; i <= n; i++) {
cin >> arr[i];
}
for (int i = 1; i <= n; i++) {
vis[i] = 201;
}
dfs(0, a, n);
if (vis[b] == 201) cout << "-1";
else cout << vis[b];
return 0;
}
#include
using namespace std;
int a,b,x[500]/*电梯上的数字*/;
bool vis[500];
int q,p; //头、尾指针
int N;
struct node
{
int floor,dep;
}Q[1000];
int bfs() //广搜
{
if(a==b) return 0; //如果开始层等于结束层,直接返回0步
int ans,top,k;
Q[1]={a,0};
q=1;p=2;
while(q=1&&k<=N&&!vis[k])
{
vis[k]=true;
if(k==b) return ans+1; //到达终点,返回答案
Q[p]={k,ans+1}; //入队列
p++;
}
}
q++;
}
return -1;
}
int main()
{
cin>>N>>a>>b;
for(int i=1;i<=N;i++) cin>>x[i];
cout<
#include
using namespace std;
int f[205][205],n,a,b,k[205];
int main(){
cin>>n>>a>>b;
for(int i=1;i<=n;i++)cin>>k[i];
f[0][a]=1;
for(int i=0;i=1)f[i+1][j-k[j]]=f[i][j];
}
}
for(int i=0;i<=n;i++){
if(f[i][b]){
cout<