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 ", 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