该题的题意比较难以理解,并且问题难以分析,,,
其中的要点就是,包含j这个点的状态的时间总值是否大于j这个点的截止时间,如果小于则扣分数为0,大于则差值就为扣分数
代码:
#include<bits/stdc++.h>
using namespace std;
const int MAX=1<<16;
int dp[MAX]; //把每一个状态中课程完成的最少用时
int t[20]; //每一门课完成所需要的时间
int d[20]; //每一门课程的截止时间
int sum[MAX]; //表示每一个状态完成所需要的时间总和
string name[20];
string ans[MAX];
int calc(int a,int b)
{
return max(0,a-b);
}
int main()
{
int T,n,i,j,_i,_j,num;
scanf("%d",&T);
while(T--)
{
scanf("%d",&n);
for(i=0,_i=1; i<n; _i<<=1,++i)
{
cin>>name[i];
scanf("%d %d",&d[i],&t[i]);
sum[_i]=t[i];
}
num=1<<n;
for(i=1; i<num; ++i)
{
for(j=0,_j=1; j<n; _j<<=1,++j)
{
if(i&_j)
{
sum[i]=sum[i-_j]+t[j];
}
}
}
dp[0]=0;
for(i=0; i<num; ++i)
ans[i]="";
for(i=1; i<num; ++i)
{
for(j=0,_j=1; j<n; _j<<=1,++j)
{
if((i&_j)&&((dp[i-_j]+calc(sum[i],d[j])<=dp[i]||ans[i]=="")))
{
if((dp[i-_j]+calc(sum[i],d[j])<dp[i])||(ans[i-_j]+name[j]+"\n"<ans[i])||(ans[i]==""))
{
ans[i]=ans[i-_j]+name[j]+"\n";
}
dp[i]=dp[i-_j]+calc(sum[i],d[j]);
}
}
}
printf("%d\n",dp[num-1]);
cout<<ans[num-1];
}
return 0;
}