传送门
- 状态转移 dp[s|(1<<(j-1))][j]=max(dp[s|(1<<(j-1))][j],dp[s][i]+ai*aj)
- 有虚假态
#include<bits/stdc++.h>
using namespace std;
#define inf 0x80000000
int dp[1<<20][20];
int a[20],p[20];
int main()
{
int t,n,s,ans;
int cas=1;
scanf("%d",&t);
while(t--){
scanf("%d",&n);
for(int i=0;i<n;i++) scanf("%d%d",&a[i],&p[i]);
for(int i=0;i<(1<<n);i++)
for(int j=0;j<n;j++)
dp[i][j]=inf;
for(int i=0;i<n;i++)
if(p[i]==0||p[i]==-1) dp[1<<i][i]=0;
for(int i=0;i<(1<<n);i++)
for(int j=0;j<n;j++)
if(dp[i][j]!=-inf)
for(int k=0;k<n;k++)
if(((1<<k)&i)==0&&(p[k]==__builtin_popcount(i)||p[k]==-1))
dp[i|(1<<k)][k]=max(dp[i|(1<<k)][k],dp[i][j]+a[j]*a[k]);
ans=inf;
for(int i=0;i<n;i++) ans=max(ans,dp[(1<<n)-1][i]);
printf("Case #%d:\n%d\n",cas++,ans);
}
return 0;
}
#include<bits/stdc++.h>
using namespace std;
const int inf=0x80000000;
const int maxn=(1<<16)+5;
int n,a[20],p[20];
int h[20];
int c[maxn];
int dp[maxn][20];
int bit(int i){
int cnt=0;
while(i) i&=i-1,cnt++;
return cnt;
}
int main()
{
int t,ans,S;
int cas=1;
for(int i=0;i<16;i++) c[1<<i]=i+1;
scanf("%d",&t);
while(t--){
scanf("%d",&n);
S=(1<<n)-1;
memset(h,-1,sizeof(h));
for(int i=1;i<=n;i++){
scanf("%d%d",&a[i],&p[i]);
if(~p[i]) h[p[i]]=i;
}
for(int i=0;i<maxn;i++)
for(int j=0;j<20;j++)
dp[i][j]=inf;
if(~h[0]) dp[1<<(h[0]-1)][h[0]]=0;
else{
for(int i=1;i<=n;i++) if(p[i]==-1) dp[1<<(i-1)][i]=0;
}
for(int nxt,i=1;i<S;i++){
nxt=bit(i);
for(int lst,j=i;j>0;j&=j-1){
lst=-j&j;
if(dp[i][c[lst]]==inf) continue;
if(~h[nxt]){
dp[i|(1<<(h[nxt]-1))][h[nxt]]=max(dp[i|(1<<(h[nxt]-1))][h[nxt]],dp[i][c[lst]]+a[c[lst]]*a[h[nxt]]);
continue;
}
for(int k=1;k<=n;k++){
if(1<<(k-1)&i) continue;
if(~p[k]&&p[k]!=nxt) continue;
dp[i|(1<<(k-1))][k]=max(dp[i|(1<<(k-1))][k],dp[i][c[lst]]+a[c[lst]]*a[k]);
}
}
}
ans=inf;
for(int i=1;i<=n;i++) ans=max(ans,dp[S][i]);
printf("Case #%d:\n%d\n",cas++,ans);
}
return 0;
}