HDU2182 Frog —— 简单DP

传送门

题意: 青蛙在起点0,可以跳k次,每次可以跳a~b的距离,每跳到一个位置,都可以迟到该位置的昆虫,包括起始位置的昆虫。问青蛙最多可以吃到多少昆虫。
题解: 用DP,用搜索都可以解决这个问题,用搜索可能更加直观,从起点跳出去,通过BFS之后更新最大值,这几乎是没有异议的。
  问题在于DP,题目当然是不难,我也很快写出一段代码,提交以后也AC了。

不严谨的代码(但能AC)

#include<iostream>
#include<algorithm>
#include<cstring>
using namespace std;

int t, n, a, b, k;
int map[110], dp[110][110];
int main(){
    scanf("%d", &t);
    while(t--){
        memset(dp, 0, sizeof dp);
        scanf("%d%d%d%d", &n, &a, &b, &k);
        for (int i = 1; i <= n; i++)    scanf("%d", map + i);
        for (int i = a; i <= n; i++)
            for (int j = 1; j <= k; j++)
                for (int l = a; l <= b; l++)
                    if(i-l > 0) dp[i][j] = max(dp[i][j], dp[i - l][j - 1] + map[i]);
        printf("%d\n", dp[n][k] + map[1]);
    }
    return 0;
}

  其状态转移方程为dp[i][j] = max(dp[i][j], dp[i - l][j - 1] + map[i]);其中dp[i][j]表示 j 步到达位置 i 。但是但是但是,我发现了一个特殊样例:

1
8 1 1 2
1 2 3 4 5 6 7 8

用肉眼观察的话,我们很容易能看出,每次都只能跳一个单位,可以跳两次。也就是说我们的青蛙能吃到位置0、1、2上的昆虫,一共为6,然而这段代码做出来,他选取了最后两个位置的昆虫,输出为16.如果如果如果我的题目理解没有错的话,可能就是题目的测试数据不够严谨了。因为我的下一段代码,修改了这部分的“我认为的”错误,提交以后仍然AC。

修改后的代码

#include<iostream>
#include<algorithm>
#include<cstring>
using namespace std;

int t, n, a, b, k;
int p[110], dp[110][110];
int main(){
    scanf("%d", &t);
    while(t--){
        int ans = 0;
        memset(dp, 0, sizeof dp);
        scanf("%d%d%d%d", &n, &a, &b, &k);
        for (int i = 0; i < n; i++) scanf("%d", p + i);
        ans = dp[0][0] = p[0];
        for (int i = 0; i < n; i++)
            for (int j = 1; j <= k; j++)
                for (int pos = i + a; pos <= i + b && pos < n; pos++){
                    if(dp[i][j - 1])
                        dp[pos][j] = max(dp[pos][j], dp[i][j - 1] + p[pos]);
                    ans = max(ans, dp[pos][j]);
                }
        printf("%d\n", ans);
    }
    return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值