题目:http://acm.hdu.edu.cn/showproblem.php?pid=5691
带一点变形的状压dp
先预处理出所有能放在首位的状态
之后判断是如果是-1直接转移,否则要先判断现在是放第几位,相等才能转移
#include<iostream> #include<cstdio> #include<cstring> #include<string> #include<cmath> #include<algorithm> #include<vector> #include<queue> #include<stack> #include<map> #include<set> using namespace std; const int N=20; const int inf=2e9; int a[N],p[N]; int dp[1<<16][16]; int f(int x) { int s=0; while(x) { s++; x-=x&-x; } return s; } int main() { int T; scanf("%d",&T); for(int ca=1;ca<=T;ca++) { int n; scanf("%d",&n); for(int i=0;i<n;i++) scanf("%d%d",&a[i],&p[i]); int tot=1<<n; for(int i=0;i<tot;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<tot;i++) { for(int j=0;j<n;j++) { if (dp[i][j]==-inf) continue; for(int k=0;k<n;k++) { if (i>>k&1) continue; if (p[k]==-1||f(i)==p[k]) dp[i|1<<k][k]=max(dp[i|1<<k][k],dp[i][j]+a[j]*a[k]); } } } int ans=-inf; for(int i=0;i<n;i++) ans=max(ans,dp[tot-1][i]); printf("Case #%d: %d ",ca,ans); } return 0; }