把每道题的前置条件用二进制压缩,然后dp枚举所有可能状态,再枚举该状态是从哪一个节点转移来的,符合前置条件则更新。
代码:
#include#include #include using namespace std;typedef long long ll;const int maxn = 1 << 20;ll dp[maxn], a[21], b[21];int pre[21];int calc(int s) { int res = 0; for (int i = 0; i < 20; i++) { if ((1 << i) & s) { res++; } } return res;}int main() { int n; memset(dp, -0x3f, sizeof dp); scanf("%d", &n); for (int i = 1, t, x; i <= n; i++) { scanf("%lld%lld%d", &a[i], &b[i], &t); while (t--) { scanf("%d", &x); pre[i] += (1 << (x - 1)); } } ll ans = 0; dp[0] = 0; for (int i = 1; i < (1 << n); i++) { for (int j = 0; j < n; j++) { if (i & (1 << j)) { int t = i - (1 << j); if ((t & pre[j + 1]) == pre[j + 1]) { dp[i] = max(dp[i], dp[t] + calc(i) * a[j + 1] + b[j + 1]); ans = max(ans, dp[i]); } } } } printf("%lld\n", ans);}