18.06.06 动规作业2

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 }
View Code

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 }
View Code

这个实现实在是太差了 但我只能想到状压dp,而且状压我也只会这么一种……

之后再回头来看看吧

百练4149

猜你喜欢

转载自www.cnblogs.com/yalphait/p/9146455.html