题目链接:卡尔的连招
设
dp2[i]
是状态为
i
时的最大值。
很容易得到状态转移方程为
其中
dp1[i][k]
是状态为
i
时,最后技能为
所以预处理出
dp1[i][k]
,状态转移方程为
dp1[i|(1<<k)][j]=max(dp1[i|(1<<k)][j],dp[i][j])
。
初始化
dp[0][j]=a[j]
,
dp[s][j]=b[j]
。
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N=15;
int a[N];
int dp[1<<N][N];
int dp2[1<<N];
int main()
{
ios::sync_with_stdio(false);
int T;
cin >> T;
while (T--)
{
int n;
cin >> n;
int total = 1 << n;
for(int i = 0; i<total; ++i)
for(int j = 0; j < n; ++j)
dp[i][j]=0;
for(int i = 0; i < n; i++)
{
int a,m;
cin >> a >> m;
dp[0][i] = a;
for(int j = 0; j < m; ++j)
{
int b,c,s=0;
cin >> b >> c;
for(int k = 0; k < c; ++k)
{
int t;
cin >> t;
s |= (1 << t);
}
dp[s][i] = max(dp[s][i], b);
}
}
for(int i = 0; i < total; ++i)
for(int j = 0; j < n; ++j)
for(int k = 0; k < n; ++k)
if(!(i&(1<<j)))
dp[i | (1 << k)][j] = max(dp[(i | (1 << k))][j], dp[i][j]);
for(int i = 0; i < total; ++i)
dp2[i]=0;
for(int i=0; i < total; ++i)
for(int j = 0; j < n; ++j)
if(i&(1<<j)) continue;
else dp2[i | (1 << j)] = max(dp2[i | (1 << j)],dp2[i] + dp[i][j]);
cout << dp2[total - 1] << endl;
}
return 0;
}