ACM-ICPC 2018 南京赛区网络预赛 - AC Challenge
题意:
有n个题目,每个题目有一些信息,
,第 t 个过第 i 题会得到分数 t*ai + bi
在过第 i 题前必须要先过
这几题,可以选择不过题
求最大得分
最多20个题目,不计顺序的话,一共有 2^20 = 1,048,576 种取法
做出 i 个可以从做出 i-1 个的状态推出,枚举第 i 个做出的题目,得到每个做出 i 个题目的最大值然后继续下推
#include <iostream>
#include <string.h>
#include <stdio.h>
#include <algorithm>
using namespace std;
typedef long long int LL;
LL n, x, s, ans, dp[1<<21];
struct node{LL a, b, p;}a[22];
LL count(LL x, int t) {
LL ans = -1e12;
for(int i=0;i<n;i++) {
if(x & (1<<i)) {
if((x & a[i+1].p) == a[i+1].p)
ans = max(ans, dp[x ^ (1<<i)] + t*a[i+1].a + a[i+1].b);
}
}
return dp[x] = ans;
}
void f(int x, int pre, int cnt, int tot) {
if(cnt == x) {
ans = max(ans, count(tot, x));
return;
}
if(n-pre < x-cnt) return;
for(int i=pre+1;i<=n;i++) f(x, i, cnt+1, tot | (1<<(i-1)));
}
int main()
{
scanf("%lld", &n);
for(int i=1;i<=n;i++) {
scanf("%lld%lld%lld", &a[i].a, &a[i].b, &s);
for(int j=1;j<=s;j++) {
scanf("%lld", &x); a[i].p |= (1<<(x-1));
}
}
for(int i=1;i<=n;i++) f(i, 0, 0, 0);
printf("%lld\n", ans);
return 0;
}