Charm Bracelet
Time Limit: 1000MS | Memory Limit: 65536K | |
Total Submissions: 49676 | Accepted: 20994 |
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
Python Version:
def knapsack(w, v, m):
n = len(w)
dp = [[0 for j in range(m + 1)] for i in range(n + 1)]
#背包问题是典型的动态规划 dp[i][j]表示用下标是0..i的背包(具体某个背包可能限定只用一次,也可能不限制用几次),总重量不超过j,能够达到的最大价值
#如何确定具体某个背包用一次还是用多次?取决于dp[i][j]的j的刷新顺序
#如果dp[i][j]刷新后的结果可以被dp[i][j+w[i]]针对i的背包来继续利用,就是放回
#反之,就是不放回
for i in range(0, n):
for j in range(w[i], m+1): #放回
dp[i][j] = max(dp[i][j], dp[i][j-w[i]]+v[i])
dp[i+1][j] = dp[i][j]
# for j in range(w[i], m+1): # 不放回,不可以利用本轮之前结果
# dp[i+1][j] = max(dp[i][j], dp[i][j - w[i]] + v[i])
# for j in range(m, w[i]-1, -1): # 不放回,不可以利用本轮之前结果
# dp[i+1][j] = max(dp[i][j], dp[i][j - w[i]] + v[i])
return dp[n][m]
if __name__ == '__main__':
w = [1, 3, 5]
v = [5, 3, 1]
res = knapsack(w, v, 40)
print(res)
/* 背包问题简洁版 ,改一下刷新的方向就是完全背包或者是不完全背包,建议对照原版看,不明白打印二维数组*/
#include<iostream>
#include<stdio.h>
using namespace std;
int mm[ 12881 ]={0};
int w[3403];
int v[3403];
int main()
{
int n,m,i,j;
scanf("%d%d",&n,&m);
for(i=0;i<n;i++)
scanf("%d%d",&w[i],&v[i]);
//mm[i][j] 表示选择在[i..n-1]容量为j情况下的最大值,但事实上用一维存就够了
for( i=n-1;i>=0;i-- )
{
//for( j=m;j>=w[i];j-- ) //从这个方向刷新是上轮的,每个宝贝at most once
//for( j=w[i];j<=m;j++ ) //从这个方向刷新的是本轮的 ,每个宝贝选择不限次数
for( j=m;j>=w[i];j-- ) //从这个方向刷新是上轮的,每个宝贝at most once
mm[j]=max( mm[j] , mm[ j-w[ i ] ] +v[i] );
}
printf("%d\n",mm[ m ]);
system("pause");
return 0;
}