poj2288(상압dp)

58706 단어 dppoj
이 문제는 세 개의 성환을 제한하고 싶지 않을 때 일차적으로 압력을 가할 수 있지만 이 조건은...그래서 이런 상태 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 0x3f3f3f3f
typedef __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
", 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
", max, sum / 2); } return 0; }

좋은 웹페이지 즐겨찾기