1. 程式人生 > >poj 2280 Islands and Bridges 哈密爾頓路 狀壓dp

poj 2280 Islands and Bridges 哈密爾頓路 狀壓dp

main dfs printf sca -i lin mes ios fine

題目鏈接

題意

給定一個\(N\)個點的無向圖,求一條哈密爾頓路徑\(C_1C_2...C_n\),使其\(value\)最大。

\(value\)的計算方式如下:\[\begin{aligned}value&=\sum_{i=1}^{n}C_i\\&+\sum_{i=1}^{n-1}C_i*C_{i+1}\\&+\sum_{i=1}^{n-2}C_i*C_{i+1}*C_{i+2}[(C_i,C_{i+2})is\ an\ edge\ in\ the\ graph]\end{aligned}\]

思路

狀態表示及轉移等與前兩題相類似。

因為狀態和前兩步相關,所以用\(dp[state][i][j]\)

表示,接連經過\(j\)點與\(i\)點到達\(state\)狀態的最大\(value\)值和對應的路徑數目。

註意答案會爆\(int\).

Code

#include <cstdio>
#include <iostream>
#include <cstring>
#define maxn 10010
#define inf 0x3f3f3f3f
#define F(i, a, b) for (LL i = (a); i < (b); ++i)
#define F2(i, a, b) for (LL i = (a); i <= (b); ++i)
#define dF(i, a, b) for (LL i = (a); i > (b); --i)
#define dF2(i, a, b) for (LL i = (a); i >= (b); --i) using namespace std; bool vis[maxn][13][13], dis[13][13]; typedef long long LL; LL v[13], n, m; struct node { LL v, w, flag; }dp[maxn][13][13]; node dfs(LL state, LL p1, LL p2) { if (state==(1<<p1)+(1<<p2)) return {v[p1]+v[p2]+v[p1]*v[p2], 1
, 1}; if (vis[state][p1][p2]) return dp[state][p1][p2]; vis[state][p1][p2] = true; LL sta = state - (1<<p1); node ans = {0, 0, 0}; bool flag = false; F(i, 0, n) { if (i==p1 || i==p2 || !dis[i][p2] || !(state&(1<<i))) continue; node nd = dfs(sta, p2, i); if (!nd.flag) continue; flag = true; LL temp = nd.v + (dis[p1][i]?v[p1]*v[p2]*v[i]:0); if (temp > ans.v) ans = {temp, nd.w}; else if (temp == ans.v) ans.w += nd.w; } if (!flag) return dp[state][p1][p2] = {0, 0, 0}; else return dp[state][p1][p2] = {ans.v + v[p1] + v[p1]*v[p2], ans.w, 1}; } void work() { memset(dis, 0, sizeof dis); memset(vis, 0, sizeof vis); memset(dp, 0, sizeof dp); scanf("%lld%lld", &n, &m); F(i, 0, n) scanf("%lld", &v[i]); F(i, 0, m) { LL u, v; scanf("%lld%lld", &u, &v); --u, --v; dis[u][v] = dis[v][u] = 1; } if (n==1) { printf("%lld %lld\n", v[0], 1); return; } node ans = {0, 0, 0}; F(i, 0, n) { F(j, 0, n) { if (i==j || !dis[j][i]) continue; node temp = dfs((1<<n)-1, i, j); if (!temp.flag) continue; if (temp.v > ans.v) ans = temp; else if (temp.v == ans.v) ans.w += temp.w; } } printf("%lld %lld\n", ans.v, ans.w>>1); } int main() { LL T; scanf("%lld", &T); while (T--) work(); return 0; }

poj 2280 Islands and Bridges 哈密爾頓路 狀壓dp