Charm Bracelet (北大MOOC程序設計與算法二 第七週題)

Charm Bracelet

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 iin 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.

輸入

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

輸出

Line 1: A single integer that is the greatest sum of charm desirabilities that can be achieved given the weight constraints

輸入樣例

4 6
1 4
2 6
3 12
2 7

輸出樣例

23

實現代碼

#include <iostream>
#include <algorithm>
using namespace std;
const int max_n=3405;
const int max_m=12900;

int weight[max_n];
int desir[max_n];
int f[max_m]={0};
int N,M;

int main(){
	cin>>N>>M;
	for(int i=1;i<=N;i++){
		cin>>weight[i]>>desir[i];
	}
	for(int i=0;i<weight[1];i++){
		f[i]=0;
	}
	for(int i=weight[1];i<=M;i++){
		f[i]=desir[1];
	}
	for(int i=2;i<=N;i++){
		for(int j=M;j>=0;j--){
			if(j>=weight[i]){
				f[j]=max(f[j],f[j-weight[i]]+desir[i]);
			}
		}
	}
	cout<<f[M];
	return 0;
}

解題思想

用 f [ i ] [ j ]表示取前 i 種魅力符,使它們總質量不超過 j 的最優取法取得的魅力值總和。

邊界條件

當只有一個魅力符的時候,選擇取與不取,即N=1。這時候如果這個物品的重量weight[1]<=M,說明可以取:f[0][M]=desir[1]。否則,weight[1]>M,說明鐲子容不下這顆:f[0][M]=0。

遞推

f [ i ][ j ]=max (f [ i -1 ][ j ], f [ i-1 ][ j-weight[ i ] ]+ desir[ i ] )。
即判斷第i種魅力符取不取,依據取與不取的結果最優來判斷,注意 j-weight[ i ]>=0時纔有第二項。

內存

用二維數組會佔用許多內存,N、M。實際上,從遞推公式可以看出,每次循環都只用到了上一行的正上方的值以及左邊的值,因此可以定義一維數組,滾動記憶。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章