【牛牛的跳跳棋】dp解法

题目大意


当棋子位于第 i 个格子时,它的下一步可以移动到[𝑖 − 𝑝𝑖, 𝑖 + 𝑝𝑖]范围内的任意一个格子,每次可以使得一个格子的弹力系数𝑝𝑖 + 1,请输出最小操作次数,以及操作序列


分析


考场上的时候,第一眼看到这道题就想到了dp,并很快定义出了状态——dp[i]表示到达第i格所需的最少操作次数,那么对于每个dp[i],它都可以更新[𝑖 − 𝑝𝑖, 𝑖 + 𝑝𝑖]范围内的dp,进一步思考,我们可以忽略掉往回走的情况,因为对于任意i,若能到达该点,那么它前面的元素也一定被走到过  
综上:用dp[i]更新dp[i+1]到dp[i+a[i]]的值,除此之外,还要考虑对p[i]进行更改的操作,所以要用dp[i]+1更新dp[i+a[i]+1]的值  

用状态转移方程打出dp后,这道题就已经解决了一半,现在需要找出更改序列,而要知道哪些p[i]被更改了,则要先求到从起点到达n+1点的路径,如果从当前点到下一个点的位移为当前p[i]+1的话,证明该点被修改 

借鉴当时学lis时输出序列的方式,定义一个数组pre,用来保存该点的前驱,最后通过n+1一步一步检索即可

代码

#include<bits/stdc++.h>
using namespace std;
const int MAXN = 1e5 + 5;
template<typename item>//方便 
void read(item &x) {
    x = 0;
    int f = 1;
    char c = getchar();
    while(c < '0' || c > '9') {
        if (c == '-') f = -1;
        c = getchar();
    }
    while(c >= '0' && c <= '9') {
        x = (x << 1) + (x << 3) + (c ^ 48);
        c = getchar(); 
    }
    x *= f;
}
int n , a[MAXN] , dp[MAXN] , pre[MAXN] , ans[MAXN] , cnt;
int main() {
    read(n);
    for (int i = 1 ; i <= n ; i ++) {
        read(a[i]);//输入 
    }
    memset(dp , 0x3f , sizeof(dp));//初始成极大值 
    dp[1] = 0;//起点在1 
    for (int i = 1 ; i <= n ; i ++) {
        for (int j = i + 1 ; j <= min(n + 1 , i + a[i]) ; j ++) {//用当前i更新其能到达的点,因为终点在 n+1,所以只需枚举到 min(n + 1 , i + a[i])即可 
            if (dp[j] > dp[i]) {//更新最小值 
                dp[j] = dp[i];
                pre[j] = i;//保存前驱,用以求出序列 
            }
        }
        if (dp[i + a[i] + 1] > dp[i] + 1) {//考虑当前点被施法了的情况,所以能走到 i+a[i]+1这个点 
            dp[i + a[i] + 1] = dp[i] + 1;
            pre[i + a[i] + 1] = i;//同样,记录前驱 
        }
    }
    printf("%d\n", dp[n + 1]);//先输出最少操作几次 
    int x = n + 1;//以终点为开始往回搜路径 
    while(pre[x]) {
        if (a[pre[x]] + pre[x] + 1 == x) {//若这次移动的路程为当前弹力系数 +1的话,证明该点被更改过 
            ans[++ cnt] = pre[x];
        }
        x = pre[x];//继续往前找,直至前驱为零 
    }
    for (int i = cnt ; i >= 1 ; i --) {
        printf("%d ", ans[i]);//输出 
    }
    return 0;
} 

posted @   Fracture_Dream  阅读(3)  评论(0编辑  收藏  举报  
相关博文:
阅读排行:
· 地球OL攻略 —— 某应届生求职总结
· 周边上新:园子的第一款马克杯温暖上架
· Open-Sora 2.0 重磅开源!
· 提示词工程——AI应用必不可少的技术
· .NET周刊【3月第1期 2025-03-02】
点击右上角即可分享
微信分享提示