hdu 5691 Sitting in Line 状压dp
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了hdu 5691 Sitting in Line 状压dp相关的知识,希望对你有一定的参考价值。
题目链接:
http://acm.hdu.edu.cn/showproblem.php?pid=5691
题解:
和tsp用的状压差不多,就是固定了一些访问顺序。
dp[i][j]表示前cnt个点中布满状态i且最后一个为j的状态的最大乘积和。
则有dp[i|(1<<k)][k]=max(dp[i|(1<<k)][k],dp[i][j]+a[j]*a[k])。
#include<iostream> #include<cstring> #include<cstdio> #include<algorithm> using namespace std; const int maxn = 22; const int INF = 2e9; int dp[1 << 16][22]; int cnt[1 << 16]; int a[maxn], p[maxn],f[maxn]; int n; void pre() { for (int i = 0; i < (1 << 16); i++) { cnt[i] = 0; for (int j = 0; j < 16; j++) { if (i&(1 << j)) cnt[i]++; } } } void init() { for (int i = 0; i < (1 << n); i++) { for (int j = 0; j <= n; j++) { dp[i][j] = -INF; } } memset(f, -1, sizeof(f)); } int main() { pre(); int tc,kase=0; scanf("%d", &tc); while (tc--) { scanf("%d", &n); init(); for (int i = 0; i < n; i++) { scanf("%d%d", a + i, p + i); if (p[i] != -1) f[p[i]] = i; } a[n] = 0; p[n] = n; dp[0][n] = 0; for (int i = 0; i < (1 << n); i++) { int sum = cnt[i]; for (int j = 0; j <= n; j++) { if ((i&(1 << j)) == 0&&j!=n) continue; //被限制的点: if (f[sum] != -1) { if ((i&(1 << f[sum])) == 0) { dp[i | (1 << f[sum])][f[sum]] = max(dp[i | (1 << f[sum])][f[sum]], dp[i][j]+a[j]*a[f[sum]]); } } else { //可以自由移动的点 for (int k = 0; k < n; k++) { if (i&(1 << k)) continue; if (p[k] ==-1) { dp[i | (1 << k)][k] = max(dp[i | (1 << k)][k], dp[i][j] + a[j] * a[k]); } } } } } int ans = -INF; for (int j = 0; j < n; j++) ans = max(ans, dp[(1 << n) - 1][j]); printf("Case #%d:\n", ++kase); printf("%d\n", ans); } return 0; }
以上是关于hdu 5691 Sitting in Line 状压dp的主要内容,如果未能解决你的问题,请参考以下文章
hdu 5691 Sitting in Line(状压dp)