hdu 1074 Doing Homework(状压)

题意:有n个作业,有截止日期和需要完成的时间,超出期限一天就扣一分。问最少扣多少分

思路:因为最多15门课,而15!太大了,所以进行状压,而2^15只有3w多,所以是可以进行的,状压后,把每种情况都枚举一下,然后同时进行时间和分数的dp,最后把分数都转移到bit-1,虽然我懂了是怎样状压dp的,但我不知道是怎么打印出来的,只知道是类似于用并查集维护一样,我打印了并查集数据也没看出来,还是不行呐

代码:

#include <bits/stdc++.h>
using namespace std;
const int maxn=(1<<15)+7;
const int inf=0x3f3f3f3f;
int n,dp[maxn],t[maxn],dea[maxn],fin[maxn],fa[maxn];
char s[20][15];

void solve(int x)
{
    if(!x)return ;
    solve(x-(1<<fa[x]));
    printf("%s\n",s[fa[x]]);
}
int main()
{
    int T;
    scanf("%d",&T);
    while(T--){
        scanf("%d",&n);
        for(int i=0;i<n;i++){
            scanf("%s%d%d",&s[i],&dea[i],&fin[i]);
        }
        int bit=1<<n;
        for(int i=1;i<bit;i++){
            dp[i]=inf;
            for(int j=n-1;j>=0;j--){
                int temp=1<<j;
                if(!(i&temp))continue;
                int ans=t[i-temp]+fin[j]-dea[j];
                if(ans<0) ans=0;
                if(dp[i]>dp[i-temp]+ans){
                    dp[i]=dp[i-temp]+ans;
                    t[i]=t[i-temp]+fin[j];
                    fa[i]=j;
                }
            }
        }
//        for(int i=0;i<bit;i++){
//            printf("fa[%d] == %d\n",i,fa[i]);
//        }
        printf("%d\n",dp[bit-1]);
        solve(bit-1);
    }
    return 0;
}

 

posted @ 2018-02-17 21:02  啦啦啦天啦噜  阅读(103)  评论(0编辑  收藏  举报