过河(离散化dp)

过河

https://ac.nowcoder.com/acm/problem/16655


题目:

青蛙要从数轴0跳到L(L最大1e9)。每次跳跃步长在[s,t]区间(s、t≤10)。数轴上有m(m最大100)个石头。问青蛙最少跳上的石头数量。


做法:

表示从0跳到i最少跳上的石头数量。枚举所有步长转移即可: 表示当前位置是否是石头。
然而发现L很大,数组开不了这么大,所以我们需要对石头间的距离进行一下处理。
发现只要,超过一定距离是必达的。
什么意思呢?比如两个石头间距离是100。
我们穷举所有情况发现必达:









故只要相邻两块石头距离≥100,我们直接模100即可。
然后就直接做dp就行了。
而当,做特判,每颗石头模s看是否等于0即可。


代码;

#include <bits/stdc++.h>
#define IOS ios::sync_with_stdio(false), cin.tie(0)
#define debug(a) cout << #a ": " << a << endl
using namespace std;
typedef long long ll;
const int N = 110;
const int M = 2e4 + 7;
const int inf = 0x3f3f3f3f;
int l, s, t, m, a[N], stone[M], dp[M];
void solve1(void){
    int cnt = 0;
    for (int i = 1; i <= m; ++i){
        if (a[i]%s == 0) cnt++;
    }
    cout << cnt << endl;
}
void solve2(void){
    int fix = 100;
    for (int i = 1; i <= m; ++i){
        a[i] = a[i-1]+(a[i]-a[i-1])%fix;
        stone[a[i]] = 1;
    }
    memset(dp, inf, sizeof dp);
    dp[0] = 0;
    for (int i = 1; i <= a[m]+fix; ++i){
        for (int j = s; j <= t; ++j){
            if (i-j < 0) continue;
            dp[i] = min(dp[i], dp[i-j]+stone[i]);
        }
    }
    int ans = inf;
    for (int i = a[m]; i <= a[m]+fix; ++i){
        ans = min(ans, dp[i]);
    }
    cout << ans << endl;
}
int main(void){ 
    IOS;
    cin >> l >> s >> t >> m;
    for (int i = 1; i <= m; ++i) cin >> a[i];
    sort(a+1, a+m+1);
    if (s == t){
        solve1();
    }else{
        solve2();
    }
    return 0;
}
全部评论

相关推荐

一个菜鸡罢了:哥们,感觉你的简历还是有点问题的,我提几点建议,看看能不能提供一点帮助 1. ”新余学院“别加粗,课程不清楚是否有必要写,感觉版面不如拿来写一下做过的事情,教育经历是你的弱势就尽量少写 2. “干部及社团经历”和“自我评价”删掉 3. 论文后面的“录用”和“小修”啥的都删掉,默认全录用,问了再说,反正小修毕业前肯定能发出来 4. 工作经验和研究成果没有体现你的个人贡献,着重包装一下个人贡献
点赞 评论 收藏
分享
点赞 收藏 评论
分享
牛客网
牛客企业服务