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


node

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.
 
 

题意:ios

有T测试用例,每一个用例有个N门做业,每门做业有截止时间和完成所需的时间,默认时间为0,在截止时间事后每拖一天就会扣一分,求作做业的顺序让扣的分最少,若是有多个答案则输出字典序最小的答案(注意!),且输入的课程名称按字母顺序递增。app

思路:测试

由于题目只有十五门课程,能够暴力状压DP,枚举1~1<<n的全部状态。具体见下代码。(不要在乎头文件)this

#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;
}
相关文章
相关标签/搜索