[HDU5691] Sitting in Line
题目
度度熊是他同时代中最伟大的数学家,一切数字都要听命于他。现在,又到了度度熊和他的数字仆人们玩排排坐游戏的时候了。游戏的规则十分简单,参与游戏的N个整数将会做成一排,他们将通过不断交换自己的位置,最终达到所有相邻两数乘积的和最大的目的,参与游戏的数字有整数也有负数。度度熊为了在他的数字仆人面前展现他的权威,他规定某些数字只能在坐固定的位置上,没有被度度熊限制的数字则可以自由地交换位置。(N<=16)
题解
dp[mask][i]表示用了mask状态的数字,处理到第i位的最大值,直接状压dp即可
代码
#include<cstring> #include<iostream> #include<stdio.h> #include<stdlib.h> #include<fstream> #include <algorithm> #include <cmath> #include<bitset> #define inf 0x3f3f3f3f using namespace std; int a[20],p[20]; int dp[1<<20][20];//状态为i最后一个数为j的最大值 int main() { int t; scanf("%d",&t); for(int x=1;x<=t;x++) { int n; 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;//只有固定放在0位的或者随意放的可以放在 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]); } } } } int full=(1<<n)-1; int ans=-inf; for(int i=0;i<n;i++) { ans=max(ans,dp[full][i]); } printf("Case #%d:\n",x); printf("%d\n",ans); } return 0; }

浙公网安备 33010602011771号