HDU1074 Doing Homework

题目

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.

Simple input

2
3
Computer 3 3
English 20 1
Math 3 2
3
Computer 3 3
English 6 3
Math 6 3

Simple output

2
Computer
Math
English
3
Computer
English
Math

题目分析

这个题目是一道很经典的壮压DP,题目中已知课程数目不会超过15门,所以可以用壮压DP来解决。难点就是构建状态转移的关系,dp数组用于保存到达状态s的最小时间,因为做一个作业开始之后,不做完是无法停下来的,所以做一个作业的时间是固定的,所以增加的时间也是固定的,而最优的办法就是到达2^n-1是的最小分数。

AC代码

1584K/0MS

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
#include <iostream>
#include <stdio.h>
#include <cstring>
#include <cmath>
#include <queue>
#include <algorithm>
#include <vector>
#include <set>
#include <map>
#include <stack>
#define MS(x,y) memset(x,y,sizeof(x))
#define MC(x,y) memcpy(x,y,sizeof(x))
void fre()
{

freopen("c://test//input.in", "r", stdin);
freopen("c://test//output.out", "w", stdout);
}
#define MP(x,y) make_pair(x,y)
typedef long long LL;
typedef unsigned long long UL;
typedef unsigned int UI;
#define debug puts("----------")
#define maxn 1050
const long long mod = 1e9+7;
const int inf = 0x3f3f3f3f;
using namespace std;
struct node
{
string name;
int dd,use;
} a[500];
struct anode
{
int time,score,pre,now;
} dp[1<<15];
int main()
{

int t,i,j,s,n,e;
scanf("%d",&t);
while(t--)
{

memset(dp,0,sizeof(dp));
scanf("%d",&n);
for(i=0; i<n; i++)
cin>>a[i].name>>a[i].dd>>a[i].use;
e = 1<<n;
for(s = 1; s<e; s++)
{
dp[s].score = inf;
for(i = n-1; i>=0; i--)
{
int tem = 1<<i;
//printf("%d %d\n",tem,s);
if(s&tem)///此处用于判断每一种情况下第i种作业是否做完
{
int past = s-tem;///当前情况下尚未做完的作业
int st = dp[past].time + a[i].use - a[i].dd;///st为倒达该状态所需要的额外花费
if(st<0)
st=0;
if(st+dp[past].score<dp[s].score)
{
dp[s].score = st + dp[past].score;
dp[s].now = i;///这种状态正在做的课程编号
dp[s].pre = past;///从past经过做i到达状态s
dp[s].time = dp[past].time + a[i].use;///更新到状态s的最小时间
}
}
}

}
stack<int>S;
int tem = e - 1;
printf("%d\n",dp[tem].score);
while(tem)
{
S.push(dp[tem].now);
tem = dp[tem].pre;
}
while(!S.empty())
{
cout<<a[S.top()].name<<endl;
S.pop();
}
}
}

题目链接

http://acm.hdu.edu.cn/showproblem.php?pid=4983