码迷,mamicode.com
首页 > 其他好文 > 详细

HDU1074:Doing Homework(状压DP)

时间:2020-04-07 18:29:08      阅读:61      评论:0      收藏:0      [点我收藏+]

标签:seve   english   empty   turn   output   efi   main   nis   hat   

 

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.
 

 

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)

标签:seve   english   empty   turn   output   efi   main   nis   hat   

原文地址:https://www.cnblogs.com/Load-Star/p/12654822.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!