hdu 5410 CRB and His Birthday(01背包+完全背包)

题目链接:

http://acm.hdu.edu.cn/showproblem.php?pid=5410

解题思路:

官方题解:

We use dynamic programming to get optimal solution.

Presents with same prices can be considered in groups.

In each group, it is needed to get the maximum number of candies that can be got when k presents are bought.

We sort the presents in non-increasing order of Ai+BiAi+Bi.

Let MAMA be the maximum of AiAitt be the minimum of index ii which satisfies inequality Ai+Bi<MAAi+Bi<MA.

We use following strategy.

If k\ <\ tk < t, then for every index from 1 to kk, buy one of that kind and get (A1+B1)+...+(Ak+Bk)(A1+B1)+...+(Ak+Bk) candies.

Else we buy one present for each index\in[1...tt] and (k-t)(kt) presents of that kind whose AA value equals MAMA. In this case we get (A1+B1)+...+(At+Bt)+(k-t)MA(A1+B1)+...+(At+Bt)+(kt)MA candies.

Let dp[n][m]dp[n][m] be the optimal value we can get passing through nn groups with mm Won.

dp[n][m]\ =\ max(dp[n-1][m-k\times\ w[n]]\ +\ opt[n][k])\ (0\ \leq \ k\ \leq \ m / w[n])dp[n][m] = max(dp[n1][mk× w[n]] + opt[n][k]) (0  k  m/w[n]).

(opt[n][k]opt[n][k]: the maximum number of candies we can get when we buy kk presents of nn-th group, w[n]w[n]: the price for nn-th group)

Time complexity:O(N\times \ (M/1\ +\ M/2\ +...+\ M/M))\ =\ O(NM\cdot logM)O(N× (M/1 + M/2 +...+ M/M)) = O(NMlogM)

首先考虑b[i]存在的情况,b[i]只会出现在第一次购买商品的时候用上,用01背包处理,然后01背包处理完后,接着跑一遍多重背包,这次仅考虑a[i]对最终结果的影响,最终输出dp[m]即为最终结果。
为什么可以这样呢?因为01背包仅仅是考虑第一次买的情况,在01背包之后跑多重背包,状态是建立在01背包的基础之上,而这正是我们需要的状态。。。

AC代码:

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

int dp[2005];
int val[1005];
int a[1005],b[1005];

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


  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值