题目链接:
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+Bi.
Let MA be the maximum of Ai, t be the minimum of index i which satisfies inequality Ai+Bi<MA.
We use following strategy.
If k < t, then for every index from 1 to k, buy one of that kind and get (A1+B1)+...+(Ak+Bk) candies.
Else we buy one present for each index∈[1...t] and (k−t) presents of that kind whose A value equals MA. In this case we get (A1+B1)+...+(At+Bt)+(k−t)MA candies.
Let dp[n][m] be the optimal value we can get passing through n groups with m Won.
dp[n][m] = max(dp[n−1][m−k× w[n]] + opt[n][k]) (0 ≤ k ≤ m/w[n]).
(opt[n][k]: the maximum number of candies we can get when we buy k presents of n-th group, w[n]: the price for n-th group)
Time complexity:O(N× (M/1 + M/2 +...+ M/M)) = O(NM⋅logM)
首先考虑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; }