分析:
看到題目第一感覺狀壓DP,由於狀壓DP要能轉移,所以需要知道當前用到的點的集合中最後一個用的點的編號。
所以轉移方程就出來了:
題目中還有一個條件,有一個固定位置,所以在轉移的時候特判一下就好了。
複雜度:
代碼:
#include <iostream>
#include <cstdio>
#include <cstring>
#include <cmath>
#include <algorithm>
#include <set>
#include <map>
#include <queue>
#include <vector>
#include <string>
using namespace std;
typedef long long LL;
typedef vector <int> VI;
typedef pair <int,int> PII;
#define FOR(i,x,y) for(int i = x;i < y;++ i)
#define IFOR(i,x,y) for(int i = x;i > y;-- i)
#define pb push_back
#define mp make_pair
#define fi first
#define se second
const LL inf = 1LL<<50;
const int maxn = 1<<16;
LL val[16],dp[maxn][16];
int n,pos[16],id[16];
void work(){
int m = 1<<n;
FOR(i,0,m) FOR(j,0,n) dp[i][j] = -inf;
if(id[0] != -1) dp[1<<id[0]][id[0]] = 0;
else{
FOR(i,0,n) dp[1<<i][i] = 0;
}
FOR(i,1,m){
int wei = __builtin_popcount(i); wei--;
FOR(j,0,n){
if((i&1<<j) == 0) continue;
if(id[wei] != -1 && id[wei] != j) continue;
int mx = i^(1<<j);
FOR(k,0,n){
if((mx&1<<k) == 0) continue;
dp[i][j] = max(dp[i][j],dp[mx][k]+val[j]*val[k]);
}
}
}
LL ans = -inf;
FOR(i,0,n) ans = max(ans,dp[m-1][i]);
printf("%I64d\n",ans);
}
int main(){
int T,tCase = 0; scanf("%d",&T);
while(T--){
printf("Case #%d:\n",++tCase);
scanf("%d",&n);
memset(id,-1,sizeof(id));
FOR(i,0,n){
scanf("%I64d%d",&val[i],&pos[i]);
if(pos[i] != -1) id[pos[i]] = i;
}
work();
}
return 0;
}