hdu 1074——Doing Homework

来源:互联网 发布:python 入门教程 知乎 编辑:程序博客网 时间:2024/06/08 05:34

题意:每个作业有最后期限和写这个作业要花费的时间。每超过最后期限一个单位时间就会减掉一分。求最少减掉多少分。
思路:状态压缩。最多15个科目。最多就15位就够了。
当这一位是1的时候就表示这个作业已经完成了。全1代表全部完成。动态规划方程:
dp(sta)=min{ dp(from) + (timeused(sta) - deadline(i) ) }
其中dp(sta)代表了在i状态的时候,最少减去的分数。timeused(sta)代表了状态i的时候,需要花费的时间。deadline(i)代表了第i门作业的最后期限。from是能到达sta的状态。from应该是跟sta只有第i位不一样。
代码如下:

#include<iostream>#include<cstdio>#include<cstring>using namespace std;int dp[1<<16];char subject[19][105];int pre[1<<16];int dl[19];int cost[19];int ans[19];int n;inline int timeused(int sta){    int ret=0;    int tot=0;    while(sta>0){        if(sta&1){            ret+=cost[tot];        }        tot++;        sta>>=1;    }    return ret;}void getans(int sta){    int tot=0;    while(sta>=0){        if(sta&1){            printf("%s\n",subject[tot]);            return;        }        tot++;        sta>>=1;    }    return;}int dfs(int sta){    if(dp[sta]>=0)return dp[sta];    for(int bit=n-1;bit>=0;--bit){//从后往前保证字典序        int sub=1<<bit;        if(sta&sub){            int from=sta^sub;            int tu=timeused(from);            int reduse=tu+cost[bit]-dl[bit];            if(reduse<0)reduse =0;            reduse+=dfs(from);            if(dp[sta]>reduse||dp[sta]==-1){                dp[sta]=reduse;                pre[sta]=from;            }        }    }    return dp[sta];}int main(){//    freopen("data.txt","r",stdin);    int T;    scanf("%d",&T);    while(T--){        scanf("%d",&n);        memset(dp,-1,sizeof(dp));        for(int i=0;i<n;++i){            scanf("%s",subject[i]);            scanf("%d%d",&dl[i],&cost[i]);        }        int last=(1<<n)-1;        dp[0]=0;        dfs(last);        printf("%d\n",dp[(1<<n)-1]);        int cnt=0;        for(int i=last;i>0;){            ans[cnt++]=i^pre[i];            i=pre[i];        }        for(int i=n-1;i>=0;--i){            getans(ans[i]);        }    }    return 0;}
0 0