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;
}
相關文章
相關標籤/搜索