poj2288(状压dp)

来源:互联网 发布:飞鱼网络电视 编辑:程序博客网 时间:2024/05/04 03:22

这题如果没想限制有三个成环的时候是可以一维转压过的,但是这个条件。。。。所以要设计这样的状态dp[s][i][j]在状态s时现在点是i上个点是j的最大值。

枚举上两个点,然后枚举这个点。

#include<iostream>#include<algorithm>#include<stdlib.h>#include<string.h>#include<stdio.h>#include<math.h>#include<string>#include<vector>#include<queue>#include<list>using namespace std;#define ep 1e-9#define oo 0x3f3f3f3ftypedef __int64 lld;lld dp[1 << 14][15][15];lld num[1 << 14][15][15];int map[15][15];lld val[15];int n, m;int main(){int T, n, m, u, v;scanf("%d", &T);while (T--){scanf("%d %d", &n, &m);for (int i = 1; i <= n; i++)scanf("%I64d", &val[i]);memset(map, 0, sizeof map);for (int i = 1; i <= m; i++){scanf("%d %d", &u, &v);map[u][v] = map[v][u] = 1;}if (n == 1){printf("%I64d 1\n", val[1]);continue;}memset(dp, -1, sizeof dp);memset(num, 0, sizeof num);int all = 1 << n;for (int i = 1; i <= n; i++)for (int j = 1; j <= n; j++){if (i == j || !map[i][j]) continue;int s1 = 1 << (i - 1);int s2 = 1 << (j - 1);dp[s1 | s2][i][j] = val[i] + val[j] + val[i] * val[j];num[s1 | s2][i][j] = 1;}for (int i = 0; i < all; i++)for (int j = 1; j <= n; j++){if (!(i&(1 << (j - 1)))) continue;for (int k = 1; k <= n; k++){if (k == j || !(i&(1 << (k - 1))) || !map[j][k]) continue;if (dp[i][j][k] == -1) continue;for (int t = 1; t <= n; t++){if (t == k || t == j) continue;if ((i&(1 << (t - 1)))) continue;if (!map[k][t]) continue;int st = i|(1 << (t - 1));lld sum = 0;sum += val[t] + val[t] * val[k];if (map[j][t]) sum += val[j] * val[k] * val[t];if (dp[i][j][k] + sum > dp[st][k][t]){dp[st][k][t] = dp[i][j][k] + sum;num[st][k][t] = num[i][j][k];}else if (dp[i][j][k] + sum == dp[st][k][t])num[st][k][t] += num[i][j][k];}}}lld max = 0, sum = 0;for (int i = 1; i <= n; i++)for (int j = 1; j <= n; j++){if (max < dp[all - 1][i][j]){max = dp[all - 1][i][j];sum = num[all - 1][i][j];}else if (max == dp[all - 1][i][j])sum += num[all - 1][i][j];}printf("%I64d %I64d\n", max, sum / 2);}return 0;}

0 0
原创粉丝点击