POJ 2288 Islands and Bridges 状态压缩DP

#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
#define LL long long
int n, m;
int v[14];
int map[14][14];
int dp[8200][14][14];
LL cnt[8200][14][14];
int main() {
	int i, j, k, x, cas;
	scanf("%d", &cas);
	while(cas--) {
		scanf("%d%d", &n, &m);
		int N = 1<<n;
		for(i = 0; i < n; i++) scanf("%d", &v[i]);
		memset(map, 0, sizeof(map));
		while(m--) {
			int x, y;
			scanf("%d%d", &x, &y); x--; y--;
			map[x][y] = map[y][x] = 1;
		}
		if(n == 1) {
			printf("%d 1\n", v[0]);
			continue;
		}
		memset(dp, -1, sizeof(dp));
		memset(cnt, 0, sizeof(cnt));
		for(i = 0; i < n; i++)
			for(j = 0; j < n; j++) if(i != j && map[i][j]) {
				dp[(1<<i)|(1<<j)][i][j] = v[i]+v[j]+v[i]*v[j];
				cnt[(1<<i)|(1<<j)][i][j] = 1;
			}
		for(i = 0; i < N; i++)
			for(j = 0; j < n; j++) if(i&(1<<j))
				for(k = 0; k < n; k++) if(i&(1<<k) && ~dp[i][j][k])
					for(x = 0; x < n; x++) if(!(i&(1<<x)) && map[k][x]) {
					    int now = dp[i][j][k]+v[x]+v[x]*v[k];
					    if(map[j][x]) now += v[x]*v[k]*v[j];
					    int state = i|(1<<x);
						if(dp[state][k][x] < now) {
						    dp[state][k][x] = now;
						    cnt[state][k][x] = cnt[i][j][k];
						}
						else if(dp[state][k][x] == now)
                            cnt[state][k][x] += cnt[i][j][k];
					}
        LL ans = 0;
        int ma = 0;
		for(i = 0; i < n; i++)
			for(j = 0; j < n; j++) if(i != j)
				ma = max(ma, dp[N-1][i][j]);
		for(i = 0; i < n; i++)
			for(j = 0; j < n; j++) if(i != j)
				if(ma == dp[N-1][i][j]) ans += cnt[N-1][i][j];
		printf("%d %I64d\n", ma, ans>>1);
	}
	return 0;
}

你可能感兴趣的:(POJ 2288 Islands and Bridges 状态压缩DP)