题意 有n个作业要做 给你每个作业的最后期限 和做完这个作业需要的时间 作业每超过最后期限一天就会扣一分 只能把一个作业做完了再做另一个作业 问做完所有作业至少扣多少分
作业最多只有15个 看到这个数字容易想到是状态压缩 dp[i]表示i对应状态的最小扣分 i转换为二进制后为1的位表明该位对应的作业已经做了 为0的位没做 那么dp[i] = min{dp[k] + cost | k为将某一位变成1后等于 i 的状态}
由于要打印路径 所有还需要记录每个状态的上一个状态pre
#include <cstdio>
#include <cstring>
using namespace std;
const int N = 16, M = 1 << N;
int d[N], c[N], n;
int dp[M], pre[M], t[M];
char s[N][105];
void print(int k)
{
if(k == 0) return;
print(pre[k]);
k -= pre[k];
for(int i = 0; i < n; ++i)
if(k & 1 << i) puts(s[i]);
}
int main()
{
int T, m, cost;
scanf("%d", &T);
while(T--)
{
scanf("%d", &n);
for(int i = 0; i < n; ++i)
scanf("%s%d%d", s[i], &d[i], &c[i]);
memset(dp, 0x3f, sizeof(dp));
dp[0] = t[0] = 0; //边界 所有