Doing Homework(hdu)1074

Doing Homework

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


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.
 

 

Author
Ignatius.L
 
思路:状压DP.
一开始想全排列,往这思路上想,这样谁都知道会超时,因为n<15;那么共有pow(2,n)的状态,那么状压dp可解决.
每个状态可由前面多个状态转移而来,所以取最小就是这个状态的最优解,局部最优,最后到整体最优。
状态转移方程和解释具体看下面代码
  1 #include<stdio.h>
  2 #include<algorithm>
  3 #include<iostream>
  4 #include<string.h>
  5 #include<stdlib.h>
  6 #include<queue>
  7 #include<stack>
  8 #define sc(x) scanf("%I64d",&x)
  9 #define pr(x) printf("%I64d",x);
 10 #define prr(x) printf("%I64d\n",x);
 11 #define prrr(x) printf(" %I64d",x);
 12 #define FOR(i,p,q) for(int i=p;i<=q;i++)
 13 int cmp(char *p,char *q);
 14 typedef struct pp
 15 {
 16     int x;
 17     int y;
 18     char a[200];
 19 } ss;
 20 ss ab[20];
 21 char bc[20][200];
 22 const int N=1e9;
 23 typedef struct qq
 24 {
 25     int time;
 26     int pre;
 27     int no;
 28     int cost;
 29 } kk;//结构体存这个状态的时间当前加入作业的编号,所罚的时间,和前一个状态
 30 kk dp[1<<15+1];
 31 using namespace std;
 32 int main(void)
 33 {
 34     int n,i,j,k,p,q;
 35     scanf("%d",&k);
 36     while(k--)
 37     {
 38         scanf("%d",&n);
 39         for(i=0; i<n; i++)
 40         {
 41             scanf("%s",ab[i].a);
 42             scanf("%d %d",&ab[i].x,&ab[i].y);
 43         }
 44         for(i=0; i<(1<<15)+1; i++)
 45         {
 46             dp[i].cost=N;
 47         }//初始化
 48         dp[0].cost=0;
 49         dp[0].pre=-1;
 50         dp[0].time=0;//开始的时间等状态
 51         for(i=1; i<(1<<n); i++)
 52         {
 53             for(j=0; j<n; j++)
 54             {
 55                 if(i&(1<<j))//当前这个状态含有第j个作业
 56                 {
 57                     if(ab[j].x<=dp[i^(1<<j)].time)//找不含j的前一个状态,并用前一个状态结束时间与第j个作业截至时间比较,然后分情况讨论下
 58                     {
 59                         int cc=dp[i^(1<<j)].time-ab[j].x;
 60                         if(dp[i].cost>dp[i^(1<<j)].cost+cc+ab[j].y)
 61                         {
 62                             dp[i].cost=dp[i^(1<<j)].cost+cc+ab[j].y;
 63                             dp[i].pre=i^(1<<j);
 64                             dp[i].no=j;
 65                             dp[i].time=dp[i^(1<<j)].time+ab[j].y;
 66                         }
 67                         else if(dp[i].cost==dp[i^(1<<j)].cost+cc+ab[j].y)
 68                         {
 69                             if(cmp(ab[j].a,ab[dp[i].no].a)>0)//按字典序排序,将最大的放最后,因为没个都是两两比较
 70                             {
 71                                 dp[i].cost=dp[i^(1<<j)].cost+cc+ab[j].y;
 72                                 dp[i].pre=i^(1<<j);
 73                                 dp[i].no=j;
 74                                 dp[i].time=dp[i^(1<<j)].time+ab[j].y;
 75                             }
 76                         }
 77                     }
 78                     else
 79                     {
 80                         int uu=ab[j].y+dp[i^(1<<j)].time;
 81                         int cc=uu-ab[j].x;
 82                         if(cc<=0)
 83                         {
 84                             if(dp[i].cost>dp[i^(1<<j)].cost)
 85                             {
 86                                 dp[i].cost=dp[i^(1<<j)].cost;
 87                                 dp[i].pre=i^(1<<j);
 88                                 dp[i].no=j;
 89                                 dp[i].time=dp[i^(1<<j)].time+ab[j].y;
 90                             }
 91                             else if(dp[i].cost==dp[i^(1<<j)].cost)
 92                             {
 93                                 if(cmp(ab[j].a,ab[dp[i].no].a)>0)
 94                                 {
 95                                     dp[i].cost=dp[i^(1<<j)].cost;
 96                                     dp[i].pre=i^(1<<j);
 97                                     dp[i].no=j;
 98                                     dp[i].time=dp[i^(1<<j)].time+ab[j].y;
 99                                 }
100                             }
101 
102                         }
103                         else
104                         {
105                             if(dp[i].cost>dp[i^(1<<j)].cost+cc)
106                             {
107                                 dp[i].cost=dp[i^(1<<j)].cost+cc;
108                                 dp[i].pre=i^(1<<j);
109                                 dp[i].no=j;
110                                 dp[i].time=dp[i^(1<<j)].time+ab[j].y;
111                             }
112                             else if(dp[i].cost==dp[i^(1<<j)].cost+cc)
113                             {
114                                 if(cmp(ab[j].a,ab[dp[i].no].a)>0)
115                                 {
116                                     dp[i].cost=dp[i^(1<<j)].cost+cc;
117                                     dp[i].pre=i^(1<<j);
118                                     dp[i].no=j;
119                                     dp[i].time=dp[i^(1<<j)].time+ab[j].y;
120                                 }
121                             }
122 
123                         }
124 
125                     }
126                 }
127             }
128         }
129       printf("%d\n",dp[(1<<n)-1].cost);
130         int pf=dp[(1<<n)-1].pre;
131         int zk=0;
132         while(zk<n-1)
133         {
134 
135             strcpy(bc[zk],ab[dp[pf].no].a);
136             zk++;
137           pf=dp[pf].pre;
138         }
139         for(i=n-2;i>=0;i--)
140         {
141             printf("%s\n",bc[i]);
142         }printf("%s\n",ab[dp[(1<<n)-1].no].a);
143     }
144 
145 
146 }
147 int cmp(char *p,char *q)
148 {
149     return strcmp(p,q);
150 }
状压DP

 

你可能感兴趣的:(Doing Homework(hdu)1074)