Codeforces Round #751 (Div. 1) B. Frog Traveler(思维题)
题意
你掉进了一个深度为n的井里,在深度为i的位置上,你可以最多跳\(a_i\)的高度,即你可以选择一个整数\(x\in [0, a_i]\),然后将高度变为\(i- x\)。你每次跳完后会休息一下,在第i个位置休息,你会下滑\(b_i\)高度,即高度变为\(i - b_i\),求最少多少次跳出井(坐标为0)。
\(1 \leq n \leq 300000\)
题解
这题vp的时候跳来跳去写晕了,写了一个搜索结果T了,官方题解写的又有点复杂,最后是在T的代码上将dfs改成bfs就过了。写篇题解来把思路理清楚。
这题如果以落下来后的位置设状态,很容易乱。因为一个极高处的点可能会落到一个很低处,于是导致状态的混乱。
但是我们可以以跳完后还未落下来的位置设置状态,对于一个相同的位置,它一定会落在一个固定的位置,我们就不管它会落在哪去了。
也就是说设dp[x]表示跳到x且还未落下来需要的次数。
我们自然希望dp[x]越小越好,如果之前有一个点比当前点能更快跳到x处,那么我们就不必考虑当前点跳到x位置了。
试着通过bfs求出所有dp值。因为每个点能跳跃的范围是一个连续的范围,所以我们依次从小到大枚举跳跃的值,最终已经遍历过的点能跳的范围一定构成一个连续的范围\([h,n]\),对于当前枚举的点我们只要考虑它是否能跳到比高度h小的位置,因为所有大于等于h的位置,前面已枚举过的点一定都能跳到而且根据bfs的性质,前面的点跳跃次数一定比当前枚举的点少。
因为每个点只会入队一次,时间复杂度为\(O(n)\)
代码
/*************************************************************************
> File Name: 1.cpp
> Author: Knowledge_llz
> Mail: 925538513@qq.com
> Blog: https://www.cnblogs.com/Knowledge-Pig/
************************************************************************/
#include<bits/stdc++.h>
#define For(i,a,b) for(int i=(a);i<=(b);++i)
#define LL long long
#define pb push_back
#define fi first
#define se second
#define pr pair<int,int>
#define mk(a,b) make_pair(a,b)
#define endl '\n'
using namespace std;
const int maxx = 5e5 + 10;
int n, a[maxx], b[maxx], dp[maxx], pre[maxx];
void bfs(){
queue<int> q;
q.push(n); dp[n] = 0;
int h = n;
while(!q.empty()){
int x = q.front(); q.pop();
// cout << x << endl;
int y = x + b[x];
for(int i = y - h + 1; i <= a[y]; ++i){
q.push(y - i);
dp[y - i] = dp[x] + 1;
pre[y - i] = x;
h = min(h, y - i);
}
}
}
int main(){
ios::sync_with_stdio(false); cin.tie(0);
#ifndef ONLINE_JUDGE
freopen("input.in", "r", stdin);
freopen("output.out","w", stdout);
#endif
cin >> n;
memset(dp, 127, sizeof(dp));
for(int i = 1; i <= n; ++i) cin >> a[i];
for(int i = 1; i <= n; ++i) cin >> b[i];
bfs();
if(dp[0] == dp[n + 1]){ cout << -1 << endl; return 0; }
cout << dp[0]<< endl;
int x = 0;
// return 0;
stack<int> ans;
while(x != n){
ans.push(x);
x = pre[x];
}
while(!ans.empty()){ cout << ans.top() << " "; ans.pop(); }
return 0;
}
```C++

浙公网安备 33010602011771号