HDU1074:Doing Homework(状压DP)
Posted load-star
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了HDU1074:Doing Homework(状压DP)相关的知识,希望对你有一定的参考价值。
Doing Homework
Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65536/32768 K (Java/Others)
Total Submission(s): 15868 Accepted Submission(s): 7718
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.
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.题意:
有T测试用例,每个用例有个N门作业,每门作业有截止时间和完成所需的时间,默认时间为0,在截止时间过后每拖一天就会扣一分,求做作业的顺序让扣的分最少,如果有多个答案则输出字典序最小的答案(注意!),且输入的课程名称按字母顺序递增。
思路:
因为题目只有十五门课程,可以暴力状压DP,枚举1~1<<n的所有状态。具体见下代码。(不要在意头文件)
#define _CRT_SECURE_NO_DepRECATE #define _CRT_SECURE_NO_WARNINGS #include <cstdio> #include <iostream> #include <cmath> #include <iomanip> #include <string> #include <algorithm> #include <bitset> #include <cstdlib> #include <cctype> #include <iterator> #include <vector> #include <cstring> #include <cassert> #include <map> #include <queue> #include <set> #include <stack> #define ll long long #define INF 0x3f3f3f3f #define ld long double const ld pi = acos(-1.0L), eps = 1e-8; int qx[4] = { 0,0,1,-1 }, qy[4] = { 1,-1,0,0 }, qxx[2] = { 1,-1 }, qyy[2] = { 1,-1 }; using namespace std; struct node { string name; int need, end; }book[20]; struct fate { int last, now, score, day; }dp[1<<15]; int main() { ios::sync_with_stdio(false); cin.tie(0); int T; cin >> T; while (T--) { int n; cin >> n; for (int i = 0; i < n; i++) { cin >> book[i].name >> book[i].end >> book[i].need; } memset(dp, 0, sizeof(dp)); for (int i = 1; i < 1 << n; i++)//枚举做作业的每种情况 { dp[i].score = INF; for (int f = n - 1; f >= 0; f--) { int s = 1 << f;//让1代表选择做哪一门课 if (s & i)//判断该情况是否有做这一门课 { int last = i - s;//last为没做s这门课的时候 int score = max(dp[last].day + book[f].need - book[f].end, 0);//计算做s这门课的时候的分数,分数不能小于0 if (score + dp[last].score < dp[i].score)//如果做s这门课得分更少则做这么课 { dp[i].score = score + dp[last].score; dp[i].day = dp[last].day + book[f].need; dp[i].last = last;//记录得分最少的上一种情况,记录路径 dp[i].now = f;//记录此时选做哪一门课,注意是倒着选的 } } } } cout << dp[(1 << n) - 1].score << endl;//(1 << n) - 1的情况即为做全部作业的时候,DP的思想。 int out = (1 << n) - 1; stack<string>output; while (out) { output.push(book[dp[out].now].name);//因为是倒着记录的所以应用stack记录然后输出 out = dp[out].last; } while (!output.empty()) { cout << output.top() << endl; output.pop(); } } return 0; }
以上是关于HDU1074:Doing Homework(状压DP)的主要内容,如果未能解决你的问题,请参考以下文章