​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;
}
//有操作的地方一定要注意优先级

​附上我大佬的递归写法​