HDU 1074 Doing Homework //超详细解释

来源:互联网 发布:国家规定加班工资算法 编辑:程序博客网 时间:2024/05/29 18:33

Doing Homework

Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others)
Total Submission(s): 5187    Accepted Submission(s): 2155


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
23Computer 3 3English 20 1Math 3 23Computer 3 3English 6 3Math 6 3
 

Sample Output
2ComputerMathEnglish3ComputerEnglishMath
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.
 

Author
Ignatius.L
#include <stdio.h>#include <string.h>#define M 1<<16struct node{    char name[200];    int deadtime;       //规定时间    int needtime;       //需要时间} course[20];struct node1{    int reduce;     //扣除分数    int cost;       //总共需要的时间    int pre;        //上一状态} dp[M];bool visit[M];  //记录状态void output(int n);int main(){    int t, n;    int i, j;    scanf("%d", &t);    while(t--)    {        scanf("%d", &n);        for(i=0; i<n; i++)            scanf("%s%d%d", course[i].name, &course[i].deadtime, &course[i].needtime);        memset(visit, false, sizeof(visit));//初始化,dp[0]代表完成0项作业        dp[0].cost = dp[0].reduce = 0;        dp[0].pre = -1;        visit[0] = true;        int all = (1<<n)-1;         for(i=0; i<all; i++)        //访问所以状态,all对应的二进制是n个1        {            for(j=0; j<n; j++)            {                int num = 1<<j;                if((i&num) == 0)    //当这个作业没有被完成时                {                    int now = num|i;       //现在对应的状态                    int cost = dp[i].cost + course[j].needtime; //当前状态需要的时间                    int reduce = cost - course[j].deadtime;     //当前状态扣除的分数                    if(reduce < 0)reduce = 0;   //扣除的分数不能为负                    reduce += dp[i].reduce;     //当前状态扣除的分数                    dp[now].cost = cost;                    if(visit[now]==true)    //当前状态没有被访问                    {                        if(dp[now].reduce > reduce)//如果此时状态扣除的分数 比 原来扣除的分数少 更新                        {                            dp[now].reduce = reduce;                            dp[now].pre = i;                        }                        else if(dp[now].reduce == reduce)   //当扣除分数相同时,选字典序小的                        {                            if(dp[now].pre > i)                                dp[now].pre = i;                        }                    }                    else    //没有被访问过                    {                        visit[now] = true;                        dp[now].reduce = reduce;                        dp[now].pre = i;                    }                }            }        }        printf("%d\n", dp[all].reduce);        output(all);    }    return 0;}void output(int n)//递归输出名字{    int last = n^dp[n].pre;     //n与dp[n].pre对应的二进制位只有一位是不同的    int num=0;    last>>=1;       //因为存course时是从0开始存的    while(last)    {        last>>=1;        num++;      //num表示1所在的位置,既是对应的第几项作业    }    if(dp[n].pre != 0)        output(dp[n].pre);    printf("%s\n", course[num].name);}



0 0
原创粉丝点击