题意:有N个问题,解决问题i之前要先解决si个问题;每分钟只能解决一个问题;每分钟必须解决一个问题,否则比赛结束。结束时获得的得分是(sum_{}{ai*t+bi}),i是解决的问题编号,t是解决该问题的时间。
分析:N不超过20,将解决问题的情况状压,用数组dp[i][s]表示第i个问题为最后解决的问题时,s解决问题为s的状态下的最高得分。而i这一维是会被覆盖的所以可以略去。
#include <bits/stdc++.h>
using namespace std;
const int maxn = 1e5+5;
typedef long long LL;
struct Node{
LL a,b;
}vz[25];
LL dp[(1<<20)];
vector<int> G[25];
LL getnum(int x)
{
LL ans=0;
while(x){
if(x&1) ans++;
x>>=1;
}
return ans;
}
bool check(int s,int i)
{
if((s&(1<<i))==0) return false;
if(dp[s^(1<<i)]==-1) return false;
for(auto &t :G[i]){
if((s&(1<<t))==0) return false;
}
return true;
}
int main()
{
#ifndef ONLINE_JUDGE
freopen("in.txt","r",stdin);
freopen("out.txt","w",stdout);
#endif
int N;
while(scanf("%d",&N)==1){
memset(dp,-1,sizeof(dp));
for(int i=0;i<=N;++i) G[i].clear();
for(int i=0;i<N;++i){
int u,v,t;
scanf("%lld %lld %d",&vz[i].a,&vz[i].b,&t);
while(t--){
scanf("%d",&u); u--;
G[i].push_back(u);
}
}
LL res=0;
int all = (1<<N)-1;
dp[0] =0;
for(int sta=1;sta<=all;++sta){
for(int i=0;i<N;++i){
if(check(sta,i)){
dp[sta] = max(dp[sta],dp[sta^(1<<i)]+vz[i].a*getnum(sta)+vz[i].b);
res = max(res,dp[sta]);
}
}
}
printf("%lld
",res);
}
return 0;
}