Charm Bracelet
Time Limit: 1000MS Memory Limit: 65536K
Description
Bessie has gone to the mall’s jewelry store and spies a charm bracelet. Of course, she’d like to fill it with the best charms possible from the N (1 ≤ N ≤ 3,402) available charms. Each charm i in the supplied list has a weight Wi (1 ≤ Wi ≤ 400), a ‘desirability’ factor Di (1 ≤ Di ≤ 100), and can be used at most once. Bessie can only support a charm bracelet whose weight is no more than M (1 ≤ M ≤ 12,880).
Given that weight limit as a constraint and a list of the charms with their weights and desirability rating, deduce the maximum possible sum of ratings.
Input
- Line 1: Two space-separated integers: N and M
- Lines 2..N+1: Line i+1 describes charm i with two space-separated integers: Wi and Di
Output
- Line 1: A single integer that is the greatest sum of charm desirabilities that can be achieved given the weight constraints
Sample Input
4 6
1 4
2 6
3 12
2 7
Sample Output
23
Source
USACO 2007 December Silver
题意
给你一个背包和一些物品,每个物品有一定的价值和重量,问如何在不超过背包存储上线的情况下使背包携带的武平价值最大,输出最大价值。
思路
标准的0-1背包,观察发现需要进行空间优化。
我们不妨思考一下,对于传统的01背包其的转移方程是
dp[i][j] = max(dp[i-1][j],dp[i-1][j-w[i]]+v[i])
即为对于当前第i件物品我们选择 要 还是 不要两种情况。
如果不要:对于容量为 j 的背包, 我们只需要它前一个状态:物品为i-1即可。
如果要:对于容量为j的背包,我们需要知道前面 容量为 j-w[i] 且武平为 i-1的背包的最大价值是多少,然后把这个物品加进去就可以啦(加了这个物品恰好把容量提升到 j )。
然后取这两个前状态的最大值即可。
如果我们把前一状态放到一起,不难发现,我们的当前状态其实一直利用迁移状态编号比我们小或者等于的一些容量为j的背包(即每次我们都查询的是容量为 j 和容量为 j-w[i]的背包)。
那么我们就从后往前更新,这样一来就不会破坏上一次的计算结果同时也能更新这一次的背包。
最后像0-1背包那样输出价值就好~
坑点
需要空间优化!
AC代码
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
int val[3403],wei[3403];
int dp[12886];
void solve(void)
{
int n,w;
while(~scanf("%d%d",&n,&w))
{
for(int i =1 ; i <= n ; i++)
{
scanf("%d%d",&wei[i],&val[i]);
}
memset(dp,0,sizeof dp);
for(int i = 1 ; i <= n ; i++)
{
for(int j = w; j >= wei[i] ; j--)
dp[j] = max(dp[j],dp[j-wei[i]]+val[i]);
}
printf("%d\n",dp[w]);
}
}
int main(void)
{
solve();
return 0;
}