hiho 7 完全背包
2015-11-06 21:23
239 查看
问题描述
有N种物品, 每种物品价值为vi, 花费为ci, 每种物品可以购买多个,现在有M单位的钱,要求能够买到的物品价值最大值。解法
类似01背包,这里只是改变了物品可以购买多个,如果还按01背包的解法,dp(i, x)表示用x钱买前i种物品,可以得到的最大值,状态转移公式为:dp(i,x)=max(dp(i−1,x−k∗ci)+k∗vi)|0≤k≤x/ci
k=0 表示不买第i种物品,k>0表示买k件第i种物品。
可以发现这样求解时存在重复的,
很容易得到下面的公式:
dp(i,x−ci)+vi=max(dp(i−1,x−ci−k∗ci)+k∗vi)+vi
0≤k≤(x−ci)/ci
=>
dp(i,x−ci)+vi=max(dp(i−1,x−ci−k∗ci)+k∗vi+vi)
0≤k≤(x−ci)/ci
=>
dp(i,x−ci)+vi=max(dp(i−1,x−(k+1)∗ci)+(k+1)∗vi)
0≤k≤(x−ci)/ci
dp(i,x−ci)+vi=max(dp(i−1,x−k′∗ci)+k′∗vi)
1≤k′≤x/ci
因此:
dp(i,x)=max(dp(i−1,x),dp(i,x−ci)+vi)
01背包时对于dp(i, 0) ~dp(i, M) 我们是从后往前求的,
现在只需要换过来从前往后求就可以了。
代码:
#include <cstdio> #include <cstring> #include <cmath> #include <algorithm> using namespace std; enum {maxn = 100000+5}; int dp[maxn]; #define OJ int main() { #ifndef OJ freopen("in.txt", "r", stdin); #endif // OJ int n, m; scanf("%d %d", &n, &m); memset(dp, 0, sizeof(int)*(m+1)); int need, value; while(n--) { scanf("%d %d", &need, &value); for (int i=need; i<= m; i++) dp[i] = max(dp[i], dp[i-need]+ value); } printf("%d\n", dp[m]); return 0; }
相关文章推荐
- 基于Android中dp和px之间进行转换的实现代码
- Android中dip、dp、sp、pt和px的区别详解
- LFC1.0.0 版本发布
- Android px、dp、sp之间相互转换
- HP data protector软件学习1--基本角色与基本工作流程
- android中像素单位dp、px、pt、sp的比较
- Android对px和dip进行尺寸转换的方法
- Android根据分辨率进行单位转换-(dp,sp转像素px)
- android 尺寸 dp,sp,px,dip,pt详解
- DP问题各种模型的状态转移方程
- POJ-1695-Magazine Delivery-dp
- nyoj-1216-整理图书-dp
- TYVJ1193 括号序列解题报告
- 对DP的一点感想
- TYVJ上一些DP的解题报告
- soj1005. Roll Playing Games
- 01背包问题
- LeetCode之Maximum Product Subarray
- DP Flow
- zoj3605 Find the Marble(三维dp)