版权声明:是自己手打的没错 https://blog.csdn.net/Mr_Treeeee/article/details/82630587
https://nanti.jisuanke.com/t/30994
题意:
每个作业都有a和b,第i次做这个作业得到的分数为i*a+b。每个作业还可能会有前置作业。
问你最大分数是多少。可以不做。
POINT:
20个作业,可以状压。时间就是这个状态1的个数。
#include <iostream>
#include <stdio.h>
#include <string.h>
#include <algorithm>
using namespace std;
#define LL long long
const int N = 20;
const LL inf = 0x3f3f3f3f3f3f3f3f;
int a[N],b[N],pre[N];
LL dp[1<<N];
int tm[1<<N];
int main()
{
tm[0]=0;
for(int i=1;i<(1<<N);i++){
tm[i]=1+tm[i-(i&-i)];
}
int n;
scanf("%d",&n);
for(int i=0;i<n;i++){
scanf("%d%d",&a[i],&b[i]);
int s;scanf("%d",&s);
for(int j=1;j<=s;j++){
int to;scanf("%d",&to);
to--;
pre[i]|=1<<to;
}
}
for(int i=1;i<(1<<n);i++) dp[i]=-inf;
dp[0]=0;
LL ans=0;
for(int i=0;i<(1<<n);i++){
if(dp[i]==-inf) continue;
for(int j=0;j<n;j++){
if((i&(1<<j))==0&&(i&pre[j])==pre[j]){
int to=i|(1<<j);
dp[to]=max(dp[to],dp[i]+1LL*(tm[i]+1)*a[j]+b[j]);
ans=max(ans,dp[to]);
}
}
}
printf("%lld\n",ans);
return 0;
}