HDU 1074 Doing Homework(状压DP输出路径)

来源:互联网 发布:ui设计前景 知乎 编辑:程序博客网 时间:2024/06/05 15:05

大概题意是有n门作业,对于每一门作业,他做完需要C天,但是作业要在D天之前交,玩一天扣一分,问如何排列作业的顺序使得扣得分最少...

状压DP,暑假的时候做过这个题目,当时没做出来找学长帮忙了...现在做起来依旧很吃力,还找出来以前的程序对照了一下...。

思路就是,当一个状态值是x的时候,他有a个1,那么x的最优情况是从有a-1个1并且加上一个1能得到x的所有状压值里面的最优解...比如完成之后是110的,他可能由010和100得到...然后只需要记录一下路径就好了....

#include<cstdio>#include<cstring>#define INF 0x3fffffffstruct node{    char name[110];    int die;    int need;}st[30];struct stsort{    int need;    int t;    int qian;}dp[1<<16];int limit;void print(int x){    int ans[30];    int l=0;    while(x>0)    {        ans[l++]=dp[x].qian;        x=x-(1<<dp[x].qian);    }    l--;    while(l>=0)    {        printf("%s\n",st[ans[l]].name);        l--;    }    return ;}int getadd(int pos,int j){    int i,top,low,sum=0;    low=dp[pos-(1<<j)].need;    top=low+st[j].need;    pos=pos-(1<<j);    for(i=0;(1<<i)<limit;i++)    {        if(((1<<i)&pos)==0)        {            if(st[i].die<top)                sum+=st[i].die<low?(top-low):(top-st[i].die);        }    }    return dp[pos].t+sum;}int main(){    int i,j,n,t;    scanf("%d",&t);    while(t--)    {        scanf("%d",&n);        limit=1<<n;        for(i=0;i<limit;i++)            dp[i].t=INF;        dp[0].t=dp[0].need=0;        for(i=0;i<n;i++)            scanf("%s %d%d",st[i].name,&st[i].die,&st[i].need);        for(i=0;i<limit;i++)        {            for(j=0;(1<<j)<=i;j++)            {                if(((1<<j)&i)!=0)                {                    if(dp[i].t>getadd(i,j))                    {                        dp[i].t=getadd(i,j);                        dp[i].need=dp[i-(1<<j)].need+st[j].need;                        dp[i].qian=j;                    }                    else if(dp[i].t==getadd(i,j)&&strcmp(st[j].name,st[dp[i].qian].name)>0)                        dp[i].qian=j;                }            }        }        printf("%d\n",dp[limit-1].t);        print(limit-1);    }    return 0;}



0 0
原创粉丝点击