题目http://acm.hdu.edu.cn/showproblem.php?pid=5691
状态DP,dp[i][j],i 表示的是一种状态,这个状态指的是当前这个数取或不取,j表示的是以第j个数结尾,
1 #include<cstdio> 2 #include<cstring> 3 #include<iostream> 4 #include<algorithm> 5 using namespace std; 6 7 typedef long long ll; 8 ll dp[1<<17][20]; 9 10 int num[20],dis[20],vis[20]; 11 ll max(ll x,ll y) {return x>y?x:y;} 12 const ll INF=1e18; 13 14 int main() 15 { 16 int t,n,pos=0; 17 scanf("%d",&t); 18 while (t--) 19 { 20 scanf("%d",&n); 21 memset(vis,-1,sizeof(vis)); 22 for(int i=0;i<(1<<n);i++) 23 for(int j=0;j<n;j++) 24 dp[i][j] = -INF; 25 for (int i=0 ; i<n ; i++) { 26 scanf("%d%d",&num[i],&dis[i]); 27 if (dis[i]!=-1) 28 vis[dis[i]]=i; 29 } 30 if (vis[0]!=-1) dp[(1<<vis[0])][vis[0]]=0;// 0这个位子被占用了 31 else{ 32 for (int i=0 ; i<n ; i++) // 没有特定位置 33 if (dis[i]==-1) dp[(1<<i)][i]=0; // 34 } 35 int cas=(1<<n)-1; 36 for (int i=1 ; i<=cas ; i++){ 37 int ans=0; 38 for (int j=0 ; j<n ; j++) 39 if (i&(1<<j)) 40 ans++; 41 if (vis[ans]!=-1) 42 { 43 ans=vis[ans]; 44 for (int j=0 ; j<n ; j++) 45 if ((i&(1<<j))&&j!=ans) 46 dp[i|(1<<ans)][ans]=max(dp[i|(1<<ans)][ans],dp[i][j]+num[j]*num[ans]); 47 } 48 else 49 { 50 for (int j=0 ; j<n ; j++){ 51 if (i&(1<<j)){ 52 for (int k=0 ; k<n ; k++){ 53 if (!(i&(1<<k))){ 54 dp[i|(1<<k)][k]=max(dp[i|(1<<k)][k],dp[i][j]+num[k]*num[j]); 55 } 56 } 57 } 58 } 59 } 60 } 61 printf("Case #%d:\n",++pos); 62 ll maxn=-INF; 63 for (int i=0 ; i<n ; i++) 64 maxn=max(maxn,dp[cas][i]); 65 printf("%I64d\n",maxn); 66 } 67 return 0; 68 }