A: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
來源
USACO 2007 December Silver

1 #include <cstdio> 2 #include <algorithm> 3 #include <stdlib.h> 4 5 using namespace std; 6 7 const int maxweight = 12900, maxnum = 3405; 8 int f[maxweight];//max desirabilities with x charms filling the weight of y 9 int n, m;//n:num of charms,m:maxweight 10 int charm[maxnum][2];//0:weight 1:desirability 11 12 void init() { 13 scanf("%d%d", &n, &m); 14 for (int i = 1; i <= n; i++) 15 scanf("%d%d", &charm[i][0], &charm[i][1]); 16 } 17 18 void dp() { 19 for(int i=1;i<=n;i++) 20 for (int j = m; j >=1; j--) { 21 if (charm[i][0] > j) 22 f[j] = f[j]; 23 else 24 f[j] = max(f[j], f[j - charm[i][0]] + charm[i][1]); 25 } 26 printf("%d\n", f[m]); 27 } 28 29 int main() 30 { 31 init(); 32 dp(); 33 return 0; 34 }
01背包
B:課程大作業
描述
小明是北京大學信息科學技術學院三年級本科生。他喜歡參加各式各樣的校園社團。這個學期就要結束了,每個課程大作業的截止時間也快到了,可是小明還沒有開始做。每一門課程都有一個課程大作業,每個課程大作業都有截止時間。如果提交時間超過截止時間X天,那么他將會被扣掉X分。對於每個大作業,小明要花費一天或者若干天來完成。他不能同時做多個大作業,只有他完成了當前的項目,才可以開始一個新的項目。小明希望你可以幫助他規划出一個最好的辦法(完成大作業的順序)來減少扣分。
輸入
輸入包含若干測試樣例。
輸入的第一行是一個正整數T,代表測試樣例數目。
對於每組測試樣例,第一行為正整數N(1 <= N <= 15)代表課程數目。
接下來N行,每行包含一個字符串S(不多於50個字符)代表課程名稱和兩個整數D(代表大作業截止時間)和C(完成該大作業需要的時間)。
注意所有的課程在輸入中出現的順序按照字典序排列。
輸出
對於每組測試樣例,請輸出最小的扣分以及相應的課程完成的順序。
如果最優方案有多個,請輸出字典序靠前的方案。
樣例輸入
2
3
Computer 3 3
English 20 1
Math 3 2
3
Computer 3 3
English 6 3
Math 6 3
樣例輸出
2
Computer
Math
English
3
Computer
English
Math
提示
第二個測試樣例, 課程完成順序Computer->English->Math 和 Computer->Math->English 都會造成3分罰分, 但是我們選擇前者,因為在字典序中靠前.

1 #include <cstdio> 2 #include <algorithm> 3 #include <stdlib.h> 4 #include <iostream> 5 6 using namespace std; 7 8 const int maxstate = 1<<16, maxday = 200,inf=9999; 9 int f[maxstate][maxday]; 10 int day[20][2];//0:deadline,1:needed time 11 char course[20][55]; 12 int n, sumday,finalstate; 13 int res[maxstate][maxday]; 14 15 void init() { 16 scanf("%d", &n); 17 sumday = 0,finalstate=(1<<(n+1))-2; 18 for (int i = 1; i <= n; i++) { 19 cin >> course[i]; 20 scanf("%d%d", &day[i][0], &day[i][1]); 21 sumday += day[i][1]; 22 } 23 for (int i = 0; i < maxstate; i++) 24 for (int j = 0; j < maxday; j++) 25 f[i][j] = inf; 26 f[finalstate][sumday] = 0; 27 } 28 29 int dp(int state,int _day) { 30 if (f[state][_day]!=inf||(state==finalstate&&_day==sumday)) 31 return f[state][_day]; 32 for (int i = 1; i <= n; i++) { 33 int flag = state & (1 << i); 34 if (!flag) 35 { 36 int extra = max(0, _day+day[i][1] - day[i][0]); 37 int tmp = dp(state + (1 << i), _day + day[i][1]) + extra; 38 if (f[state][_day] > tmp) 39 { 40 f[state][_day] = tmp; 41 res[state][_day] = i; 42 } 43 } 44 } 45 return f[state][_day]; 46 } 47 48 int main() 49 { 50 int t; 51 scanf("%d", &t); 52 while (t--) 53 { 54 init(); 55 cout << dp(0, 0)<<endl; 56 int s =0, d =0; 57 for (int i = 1; i <= n; i++) 58 { 59 cout << course[res[s][d] ]<< endl; 60 int _s = s, _d = d; 61 s += 1 << res[_s][_d]; 62 d+= day[res[_s][_d]][1]; 63 } 64 } 65 return 0; 66 }
這個實現實在是太差了 但我只能想到狀壓dp,而且狀壓我也只會這么一種……
之后再回頭來看看吧
百練4149