Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65536/32768 K (Java/Others)
Total Submission(s): 3150 Accepted Submission(s): 1203
1 #include <iostream> 2 #include <cstdio> 3 #include <cstdlib> 4 #include <ctime> 5 #include <map> 6 #include <cstring> 7 #include <string.h> 8 #include <fstream> 9 #include <vector> 10 #include <cmath> 11 #include <algorithm> 12 13 using namespace std; 14 15 const int INF = 1<<30; 16 const int N = 20; 17 18 struct work{ 19 char name[N]; //课程名字 20 int deadline; //截止时间 21 int use_time; //需要时间 22 }; 23 24 work data[N+1]; 25 26 struct state{ 27 int used_time; //已经使用时间 28 int reduce_score; //减掉的最小学分 29 int last_work; //此状态下前一个工作 30 int ith_work; //这个状态完成的最后一个工作 31 }; 32 33 state d[1<<N]; 34 35 int main() 36 { 37 int tot, n, i, j, max_value; 38 scanf("%d", &tot); 39 while (tot--) 40 { 41 scanf("%d", &n); 42 for (i=0; i<n; i++) 43 { 44 scanf("%s",&data[i].name); 45 scanf("%d%d", &data[i].deadline, &data[i].use_time); 46 } 47 max_value = (int)(1<<n); 48 int temp, score, last, reduce; 49 d[0].reduce_score = 0; 50 d[0].used_time = 0; 51 d[0].last_work = -1; 52 for (i=1; i<max_value; i++) //相当于自下而上进行DP 53 { 54 d[i].reduce_score = INF; 55 /* 56 为什么j要从后往前枚举: 57 比如i的二进制=11,则应考虑1、完成01后最小花费+10的花费 58 2、完成10后最小花费+01的花费 59 两个值较小的那一个,如果相等当然是取1,其他情况类推 60 这和题目要求的字符串升序排列有关,与最小值无关 61 */ 62 for (j=n-1; j>=0; j--) 63 { 64 temp = (int)(1<<j); 65 //如果状态i中完成了第j个作业 66 if (i & temp) 67 { 68 //如果i==temp即只完成j则last=0; 69 //则d[0].reduce_score = 0; 70 // d[0].used_time = 0; 71 // d[0].last_work = -1; 72 //如果i!=temp,则 73 //比如i=7,设被扣学分score[7]=min(score[3]+完成3后完成4被扣的学分, 74 // score[6]+完成6后完成1被扣的学分, 75 // score[5]+完成5后完成2被扣掉的学分) 76 last = i-temp; 77 //如果有足够的时间达到j状态,则求得的是在这个状态完成并被扣学分最小的情况下完成这个作业被扣的学分 78 // 否则则置为0 79 // 上一个状态所花的时间 + 完成第j个课程所花的时间 - 这门课的最后期限 80 reduce = d[last].used_time + data[j].use_time - data[j].deadline; 81 reduce = reduce>0?reduce:0; 82 //(没有完成这个作业的某个状态被扣的学分 + 在这个状态完成并被扣学分最小的情况下完成这个作业被扣的学分) < i状态下被扣学分,就更新 83 if (d[last].reduce_score + reduce < d[i].reduce_score) 84 { 85 d[i].reduce_score = d[last].reduce_score+reduce; 86 d[i].last_work = last; 87 d[i].ith_work = j; 88 d[i].used_time = d[last].used_time+data[j].use_time; 89 } 90 } 91 } 92 } 93 printf("%d\n", d[max_value-1].reduce_score); 94 int pos[N+1], k=0, x=max_value-1; 95 //递推得出序列 96 while (x > 0) 97 { 98 pos[k++] = d[x].ith_work; 99 x = d[x].last_work; 100 } 101 for (i=k-1; i>=0; i--) 102 printf("%s\n",data[pos[i]].name); 103 } 104 return 0; 105 }