【HDOJ】1074 Doing Homework
最开始以为是贪心,不过写到一半发现不对,看了一下讨论,知道需要使用状态压缩DP,现在还没有使用深搜实现(据说可以)晚上实现一下,道理应该是类似的。前面做八数码,至今未果,就说需要状态压缩。这个太神奇了,因为题目的数据量为15,所以采用移位压缩。即100代表第三个(注意index)的转台为完成。RE了很多次,才发现异或后求得的不是index。。。而且原来的输入数据本身就是字典序,不需要再strcmp,就一直RE在那个if了。
1 #include <stdio.h> 2 #include <stdlib.h> 3 #include <string.h> 4 5 #define MAXNUM 16 6 #define MAXDP 1<<15 7 8 typedef struct { 9 int pre; 10 int reduce; 11 int complete; 12 } dp_st; 13 14 dp_st dps[MAXDP]; 15 char visit[MAXDP]; 16 char stack[MAXNUM][105]; 17 18 typedef struct { 19 char name[105]; 20 int dead, need; 21 } homework_st; 22 23 homework_st homeworks[MAXNUM]; 24 25 void printCourse(int end) { 26 int top=0, now=end, id, tmp; 27 28 while (now) { 29 id = now ^ dps[now].pre; 30 tmp = 0; 31 while (id) { 32 id = id>>1; 33 ++tmp; 34 } 35 strcpy(stack[top++], homeworks[tmp-1].name); 36 now = dps[now].pre; 37 } 38 39 while (top) { 40 --top; 41 printf("%s\n", stack[top]); 42 } 43 } 44 45 int main() { 46 int case_n, n, len; 47 int i, j, k, code, tmp, complete, reduce; 48 //FILE *fout = fopen("data", "w"); 49 50 scanf("%d", &case_n); 51 52 while (case_n--) { 53 scanf("%d%*c", &n); 54 for (i=0; i<n; ++i) 55 scanf("%s %d %d", homeworks[i].name, &homeworks[i].dead, &homeworks[i].need); 56 memset(visit, 0, sizeof(visit)); 57 len = 1<<n; 58 dps[0].pre = -1; 59 dps[0].reduce = 0; 60 dps[0].complete = 0; 61 visit[0] = 1; 62 // 0~len-1 63 for (i=0; i<len-1; ++i) { 64 for (j=0; j<n; ++j) { 65 code = 1<<j; 66 // code is not done 67 if ((i&code) == 0) { 68 k = i|code; 69 complete = dps[i].complete + homeworks[j].need; 70 tmp = complete - homeworks[j].dead; 71 if (tmp < 0) 72 tmp = 0; 73 reduce = dps[i].reduce + tmp; 74 if ( visit[k] ) { 75 if (reduce < dps[k].reduce) { 76 dps[k].reduce = reduce; 77 dps[k].complete = complete; 78 dps[k].pre = i; 79 } 80 /* No need and tmp need to while(){>>1} again 81 else if (reduce == dps[k].reduce){ 82 tmp = dps[k].pre ^ k; 83 if (strcmp(homeworks[j].name, homeworks[tmp].name) < 0) { 84 dps[k].reduce = reduce; 85 dps[k].complete = complete; 86 dps[k].pre = i; 87 } 88 }*/ 89 } else { 90 visit[k] = 1; 91 dps[k].reduce = reduce; 92 dps[k].complete = complete; 93 dps[k].pre = i; 94 } 95 } 96 } 97 } 98 /* 99 for (i=0; i<len; ++i) 100 fprintf(fout, "%d: pre=%d,reduce=%d,complete=%d\n", i,dps[i].pre,dps[i].reduce,dps[i].complete); 101 */ 102 printf("%d\n", dps[len-1].reduce); 103 printCourse(len-1); 104 } 105 106 //fclose(fout); 107 return 0; 108 }