Doing Homework HDU - 1074

Doing Homework HDU - 1074
题意:做作业
题目背景是小明比赛回来一堆作业要写,不按时交作业老师就扣他平时分,晚交一天扣一分。写作业要很长时间的,安排一个写作业顺序,让小明扣分最少。
输入:T表示多组测试数据,每组数据开始n,表示有多少作业,下面n行每行输入科目,和两个正整数表示D截止日期,C表示花费时间。
输出:最少要扣的分数,和完成作业的顺序。(扣分相同输出”先后出现的顺序“ )

第一次写状态压缩的题,很艰难的理解了挺久。主要对操作符的不是很熟悉,以前也没怎么用过。看了挺多,题解,递推的写着比较简介。
下面代码注释中有我自己的理解。
有什么需要解释的都欢迎评论讨论。

#include<iostream>
#include<cstdio>
#include<cstring>
using namespace std;
const int inf=0x7f7f7f7f;
int dead[20],cost[20],dp[1<<16],time[1<<16],fa[1<<16];
char name[20][110]; 
//dp是当前状态需要消耗的最小,time是当前状态所消耗的实践,fa是父节点
 void out(int u)
 {
    if(!u) return;
    out(u-(1<<fa[u]));
    printf("%s\n",name[fa[u]]);
 } 
int main()
{
    int T,n;
    scanf("%d",&T); 
    while(T--)
    {
        scanf("%d",&n);
        for(int i=0;i<n;i++)
        scanf("%s%d%d",name[i],&dead[i],&cost[i]);
        for(int i=1;i<(1<<n);i++)
        {
            dp[i]=inf;
            for(int j=n-1;j>=0;j--)
            {
                int tmp=1<<j;//j作业写过的状态 (j表示第j个作业写过) 
                if(!(i&tmp)) continue;//i中不包含j状态 
                int v=time[i-tmp]+cost[j]-dead[j]; //从i-tmp状态到i状态的扣分 
                if(v<0) v=0; 
                if(dp[i]>dp[i-tmp]+v) 
                {
                    dp[i]=dp[i-tmp]+v;
                    time[i]=time[i-tmp]+cost[j];
                    fa[i]=j;//当前状态是由写了j作业来的 
                }
            }
        }
        printf("%d\n",dp[(1<<n)-1]);//-的优先级大于<<移 
        out((1<<n)-1); 
    }
    return 0;
} 
//有操作的地方一定要注意优先级

附上我大佬的递归写法

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值