HDU 1074 Doing Homework 状态压缩DP

题目链接http://acm.hdu.edu.cn/showproblem.php?pid=1074

题目大意:小明打完比赛回来补作业,N个作业每个作业有 名字,截止日期,完成所需时间 三个属性,如果完成时间>截止日期,就会被扣分,多一天扣一分。现在你帮他安排做作业计划。N < 15

解题思路:其实很明确的是这是个决策性问题。每次都要做一个决策,从N个作业中选出来一个来做,那么问题就是多个决策,每个决策有N种可选,如何做出决策? 那么就是典型的DP了。

状态:已经完成了m个作业------->>接下来要做第m+1个作业

转移:可以从已经做得作业中选出来m个,看已用时间,然后计算做第m+1个作业的扣分情况。

那么dp[S] :=完成S集合中的作业所扣的分数最小值。

dp[S] = min(dp[S^X] + S^X用时-第X个作业截止日期)  X 为1 ~ N中的任意一个作业且 S & X != 0

由于N < 15,所以可以采用状态压缩方式,每一位表示一个作业,1为选择了,0为未选择。

代码:

 1 const int maxn = 20;
 2 const int maxm = (1 << 15) + 5;
 3 struct sub{
 4     int dl, ti, name;
 5 };
 6 char str[maxn][105];
 7 sub subs[maxn];
 8 int n;
 9 int csb[maxn], dp[maxm], tis[maxm], pre[maxm], curs[maxm];
10 
11 void solve(){
12     for(int i = 1; i <= n; i++) csb[i] = 1 << (i - 1);
13     
14     memset(dp, 0x3f, sizeof(dp));
15     memset(tis, 0, sizeof(tis));
16     memset(pre, 0, sizeof(pre));
17     
18     const int cnt = 1 << n;
19     for(int i = 1; i < cnt; i++){
20         int x = i, st = 1;
21         while(x){
22             tis[i] += (x & 1) * subs[st].ti;
23             x >>= 1; st++;
24         }
25     }
26     dp[0] = 0;
27     for(int i = 1; i < cnt; i++){
28         for(int j = 1; j <= n; j++){
29             int tmp = tis[csb[j] ^ i] + subs[j].ti - subs[j].dl;
30             if(tmp < 0) tmp = 0;
31             if((i & csb[j]) && dp[csb[j] ^ i] + tmp <= dp[i]){
32                 dp[i] = dp[csb[j] ^ i] + tmp;
33                 pre[i] = csb[j] ^ i;
34                 curs[i] = j;
35             }
36         }
37     }
38     printf("%d
", dp[cnt - 1]);
39     stack<int> s;
40     int st = cnt - 1;
41     int sst = curs[st];
42     while(st > 0){
43         s.push(subs[sst].name);
44         st = pre[st];
45         sst = curs[st];
46     }
47     while(!s.empty()){
48         int u = s.top(); s.pop();
49         printf("%s
", str[u]);
50     }
51     
52     return;
53 }
54 int main(){
55     int T;
56     scanf("%d", &T);
57     while(T--){
58         scanf("%d", &n);
59         for(int i = 1; i <= n; i++){
60             scanf("%s %d %d", str[i], &subs[i].dl, &subs[i].ti);
61             subs[i].name = i;
62         }
63         solve();
64     }
65 }

题目:

Doing Homework

Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others)
Total Submission(s): 9876    Accepted Submission(s): 4725


Problem Description
Ignatius has just come back school from the 30th ACM/ICPC. Now he has a lot of homework to do. Every teacher gives him a deadline of handing in the homework. If Ignatius hands in the homework after the deadline, the teacher will reduce his score of the final test, 1 day for 1 point. And as you know, doing homework always takes a long time. So Ignatius wants you to help him to arrange the order of doing homework to minimize the reduced score.
 
Input
The input contains several test cases. The first line of the input is a single integer T which is the number of test cases. T test cases follow.
Each test case start with a positive integer N(1<=N<=15) which indicate the number of homework. Then N lines follow. Each line contains a string S(the subject's name, each string will at most has 100 characters) and two integers D(the deadline of the subject), C(how many days will it take Ignatius to finish this subject's homework). 

Note: All the subject names are given in the alphabet increasing order. So you may process the problem much easier.
 
Output
For each test case, you should output the smallest total reduced score, then give out the order of the subjects, one subject in a line. If there are more than one orders, you should output the alphabet smallest one.
 
Sample Input
2 3 Computer 3 3 English 20 1 Math 3 2 3 Computer 3 3 English 6 3 Math 6 3
 
Sample Output
2 Computer Math English 3 Computer English Math
Hint
In the second test case, both Computer->English->Math and Computer->Math->English leads to reduce 3 points, but the word "English" appears earlier than the word "Math", so we choose the first order. That is so-called alphabet order.
 
Author
Ignatius.L
 
原文地址:https://www.cnblogs.com/bolderic/p/7359905.html