题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=5691
dp[st][j] 表示我们选择的数的状态为ST 放在序列的前count(ST)位上 且最后一位是第J个数的时候的最大收益
采用刷表法
代码:
#include <bits/stdc++.h>
#define sf scanf
#define pf printf
using namespace std;
typedef long long LL;
#define N 1 << 17
#define maxn 17
const int INF = 2e9;
int dp[N][maxn];
int counts[N],A[maxn],P[maxn];
int main(){
int T;sf("%d",&T);
for(int i = 0;i < N;++i) counts[i] = __builtin_popcount(i);
for(int cas = 1;cas <= T;++cas){
int n,U;sf("%d",&n);
for(int i = 0;i < n;++i) sf("%d %d",A + i,P + i);
A[n] = 0;
U = 1 << n;
for(int i = 0;i < U;++i)
for(int j = 0;j <= n;++j) dp[i][j] = -INF;
dp[0][n] = 0;
for(int i = 0;i < U;++i){
for(int j = 0;j <= n;++j){
if(dp[i][j] != -INF){
for(int k = 0;k < n;++k){
if( (i >> k & 1) == 0 && (P[k] == -1 || P[k] == counts[i])){
dp[1 << k | i][k] = max(dp[1 << k | i][k],dp[i][j] + A[j] * A[k]);
}
}
}
}
}
int ans = -INF;
for(int i = 0;i < n;++i) ans = max(ans,dp[U - 1][i]);
pf("Case #%d:\n%d\n",cas,ans);
}
}