HDU

来源:互联网 发布:手机淘宝自动秒杀软件 编辑:程序博客网 时间:2024/06/07 06:09

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

题目大意: 一共有N种作业要去作, 每个作业都有一个最后期限,和要完成需要花费的时间。每项作业晚交一天,就会有一天的罚时, 问你怎么安排作业才能让罚时最少, 并输出完成作业是先后顺序。
大体思路: 因为作业数量不多, 用int的15位表示表示一项作业是否完成(1代表完成,0代表没完成, 可能和一些人表示法不一样), 枚举出所有方案并动态规划。

#include <bits/stdc++.h>using namespace std;struct info//用来记录输入的结构体{    char name[150];//作业的名字    int dea;//最后期限    int tim;//完成所需的时间}a[20];struct node//用于dp的结构体{    int penalty;//记载罚时    int time;//记载此状态下当前时间    int pre;//上一项完成的作业,指向a的下标    int now;//记载当前完成的作业}dp[(1 << 15) + 1];void _back(int n)//用于回溯输出完成方案{    if(dp[n].pre == -1)    {        return;    }    _back(dp[n].pre);    printf("%s\n", a[dp[n].now].name);}int main(){    int t, n;    while(scanf("%d",&t)!= EOF)    {        while(t-- && scanf("%d", &n))        {            for(int i = 0; i < n; i++)            {                scanf("%s %d %d", a[i].name, &a[i].dea, &a[i].tim);                getchar();            }            int enu = (1 << n);//所有可行的enu - 1种方案            for(int i = 0; i <= enu; i++)//结构体初始化, 罚时设为无穷            {                dp[i].penalty = 0x3f3f3f3f;                dp[i].time = 0;            }            dp[0].penalty = 0;            dp[0].pre = -1;//标记最开始的状态            for(int i = 1; i < enu; i++)//枚举各种方案            {                for(int j = n - 1; j >= 0; j--)//把int 15位跑一遍                {                    int tmp = (1 << j);//将1送到j位                    if(tmp & i)//判断这位是否为1                    {                        int past = i - tmp;//上一个此作业未完成的状态                        int x = dp[past].time + a[j].tim - a[j].dea;//从上一状态到这一状态的罚时                        x = max(0, x);                        if(x + dp[past].penalty < dp[i].penalty)//从上一状态到这一状态罚时小于当前已有的罚时时更新                        {                            dp[i].penalty = x + dp[past].penalty;                            dp[i].time = dp[past].time + a[j].tim;                            dp[i].pre = past;//记载路径,方便back函数回溯                            dp[i].now = j;                        }                    }                }            }            printf("%d\n", dp[enu - 1].penalty);            _back(enu - 1);//回溯输出路径        }    }    return 0;}
原创粉丝点击