HDU1074:Doing Homework

传送门

题意

给出n个任务的结束时间和持续时间,完成一个任务扣掉的分数为完成时间-结束时间,问最少扣掉多少分数

分析

观察到n为15,那么
我们将任务完成情况保存为状态,dp[i]表示到达i状态所扣的最少分数。
dp[i]由哪些状态到达?
枚举任务,对于第k个任务,在j中对于i中的任务只有k未完成,$$dp[i]=min(dp[j]+score)$$
对于路径建立一个pre数组
-END-

代码

#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;

#define ll long long
#define F(i,a,b) for(int i=a;i<=b;++i)
#define R(i,a,b) for(int i=a;i<b;++i)
#define mem(a,b) memset(a,b,sizeof(a))
const int inf=0x3f3f3f3f;
char s[20][111];
int t,n,dead[20],cost[20],pre[1<<17],dp[1<<17],tim[1<<17];
void output(int x)
{
    if(x==0) return ;
    output(x-(1<<pre[x]));
    printf("%s\n",s[pre[x]]);
}
int main()
{
    for(scanf("%d",&t);t--;)
    {
        scanf("%d",&n);
        R(i,0,n)
        {
            scanf("%s%d%d",&s[i],dead+i,cost+i);
        }
        for(int i=1;i<(1<<n);++i) {dp[i]=inf;}
        for(int i=1;i<(1<<n);++i)for(int k=n-1;k>=0;--k)
        {
            int j=i-(1<<k);
            if((1<<k)&i)
            {
                int score=max(tim[j]+cost[k]-dead[k],0);
                if(dp[i]>dp[j]+score)
                {
                    dp[i]=dp[j]+score;
                    tim[i]=tim[j]+cost[k];
                    pre[i]=k;
                }
            }

            //printf("pre[%d]=%d\n",i,pre[i]);
           //printf("tim[%d]=%d dp[%d]=%d\n",i,tim[i],i,dp[i]);
        }
        //for(int i=1;i<(1<<n);++i) printf("pre[%d]=%d\n",i,pre[i]);
        printf("%d\n",dp[(1<<n)-1]);
        output((1<<n)-1);
    }
    return 0;
}
posted @ 2017-03-23 00:11  遗风忘语  阅读(105)  评论(0编辑  收藏  举报