HDU 1074 Doing Homework

动态规划,先算只做一个homework的罚分,接着算2个、3个。。网上找来找去只有一份代码,被copy来copy去,所以我把自己的代码贴上来。

HDU 1074 Doing Homework_第1张图片

这个是HDU的acm课件里面的截图。有点像数塔。不过状态不好保存。

 

 

//46MS 1112K 1791B G++ //使用状态压缩,如01001(二进制)表示做了第一个和第四个作业。 #include <stdio.h> #include <string.h> struct dp_node { int cost,end_time; char path[16]; }; struct subject_node { char name[103]; int d,c; }; subject_node sub[15]; int q[1<<15]; //队列记录状态编号 dp_node dp[1<<15]; //每个状态的编号作为下标 int t,n; int head,tail; void print_list(char *s) { for (int i=0; i<strlen(s); ++i) { printf("%s/n", sub[s[i]-'A'].name); } } int main(int argc, char *argv[]) { scanf("%d",&t); while ( t-- ) //使用队列保证先计算1个homework,然后2个、3个。。。 { scanf("%d",&n); for (int i=0; i<n; ++i) { scanf("%s%d%d",sub[i].name, &sub[i].d, &sub[i].c); } memset(dp, -1, sizeof(dp)); head=0; tail=0; q[0]=0; dp[0].end_time=0; dp[0].cost=0; dp[0].path[0]='/0'; while ( head<=tail ) { int pt=head; ++head; for (int i=0; i<n; ++i) { if ( (q[pt] & (1<<i) )==0 ) //第i个作业还没做? { int tmp=dp[ q[pt] ].cost; char tmp_path[16]; int next= q[pt] |(1<<i); strcpy(tmp_path, dp[ q[pt] ].path); int len=strlen( tmp_path); tmp_path[ len ]=i+'A'; tmp_path[ len+1 ]='/0'; if (dp[ q[pt] ].end_time+sub[i].c>sub[i].d) //计算罚分 { tmp+= sub[i].c+dp[ q[pt] ].end_time-sub[i].d; } if ( dp[ next ].cost==-1 ) //该节点还未入队? { dp[ next ].cost=tmp; dp[ next ].end_time= dp[ q[pt] ].end_time+sub[i].c; strcpy( dp[ next ].path, tmp_path); ++tail; q[tail]=next; } else if ( dp[ next ].cost>tmp ) //已入队,但找到更小值。更新节点 { dp[ next ].cost=tmp; dp[ next ].end_time= dp[ q[pt] ].end_time+sub[i].c; strcpy( dp[ next ].path, tmp_path); } } } } printf("%d/n", dp[(1<<n) -1].cost); print_list(dp[(1<<n)-1].path); } return 0; }

 

你可能感兴趣的:(c,struct,list,homework,Path,作业)