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


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM