CF1602D. Frog Traveler 1900 ——bfs

CF1602D

题意:

从井底距离地面  处跳到地面。当距离地面  时,可以选择 [公式] 的一个数且向上跳 [公式] ,然后在 [公式] 处休息。然而,当在距离地面 [公式] 时休息,会下滑 [公式] 。问最少需要跳跃的次数,及每次跳跃后(下滑之前)的位置。

思路:

bfs

注意此题和普通bfs不同的地方在于一般的bfs都可以对某个点 遍历所有它能到达的点

但这道题若如此做会t,考虑到假如我们从i跳到j,滑落到k,如果k已经被访问过了,那么就没有了访问j的意义。所以我们用vis[]数组表示k是否被访问过,用set表示所有能到达的j,这样所有点最多被访问2次(k, j)各一次,时间复杂度O(nlogn).

但是写set时re了很多次,注意不要让迭代器越界。insert一个负数,如果迭代器访问到了负数那就说明此时容器中只有这一个元素了,及时break

// Decline is inevitable,
// Romance will last forever.
#include <bits/stdc++.h>
using namespace std;
#define mp make_pair
#define pii pair<int,int>
#define pb push_back
#define fi first
#define se second
#define ll long long
#define LL long long
//#define int long long
const int maxn = 3e5 + 10;
const int maxm = 1e3 + 10;
const int INF = 0x3f3f3f3f;
const int dx[] = {0, 0, -1, 1}; //{0, 0, 1, 1, 1,-1,-1,-1}
const int dy[] = {1, -1, 0, 0}; //{1,-1, 1, 0,-1, 1, 0,-1}
const int P = 1e9 + 7;
int n;
int a[maxn];
int b[maxn];
int pre[maxn];
int ans[maxn];
bool vis[maxn];
set<int> s;
inline int readint(){
    int a = 0, c = getchar(), f = 1;
    for(; '0'>c||c>'9'; c=getchar())
        if(c == '-') f = -f;
    for(; '0'<=c&&c<='9'; c=getchar())
        a = (a<<3)+(a<<1)+(c^48);
    return a*f;
}
void writeint(int x){
    if(x > 9) writeint(x/10);
    putchar((x-x/10*10)^48);
}
void solve() {
    n = readint();
    for(int i = 1; i <= n; i++) a[i] = readint();
    for(int i = 1; i <= n; i++) b[i] = readint();
    for(int i = 0; i <= n; i++) pre[i] = -1;
    for(int i = 0; i < n; i++) s.insert(i);
    s.insert(-999999);
    queue<pii > q;
    q.push({n, n});
    vis[n] = 1;
    while(!q.empty()) {
        pii x = q.front();
        q.pop();
        if(x.first - a[x.first] <= 0) {
            pre[0] = x.second;
            break;
        }
        for(set<int>::iterator i = --s.upper_bound(x.first); x.first-(*i) <= a[x.first]; ) {
//            cout << *i;
            if(vis[(*i)+b[*i]]) {
                int it = (*i);
                i--;
                s.erase(it);
                continue;
            }
            vis[(*i) + b[*i]] = 1;
            pre[*i] = x.second;
            q.push({(*i) + b[*i], (*i)});
            i--;
            if(*i < 0) break;
        }
    }
    if(pre[0] == -1) {
        cout << -1 <<'\n';
        return;
    }
    /*
    vector<int> ans;
    int index = 0;
    while(index != n) {
        ans.pb(index);
        index = pre[index];
    }
    printf("%d\n", (int)ans.size());
    for(int i = (int)ans.size() - 1; i >= 0; i--)
        printf("%d ", ans[i]);
    printf("\n");
     */
    int index = 0;
    int p = 0;
    while(index != n) {
        ans[++p] = index;
        index = pre[index];
    }
    printf("%d\n", p);
    for(int i = p; i >= 1; i--)
        printf("%d ", ans[i]);
    printf("\n");
}
int main() {
    solve();
    return 0;
}

猜你喜欢

转载自blog.csdn.net/m0_59273843/article/details/120979642