码迷,mamicode.com
首页 > 其他好文 > 详细

hdu 4936 Rainbow Island (状压dp+高斯消元)

时间:2016-05-07 10:48:42      阅读:162      评论:0      收藏:0      [点我收藏+]

标签:

#include <iostream>
#include <cstdio>
#include <cstring>
#include <cmath>
#include <vector>
#include <queue>
#include <map>
#include <set>
#include <algorithm>
#include <ctime>
#pragma comment(linker,"/STACK:102400000,102400000")
using namespace std;


#define eps 1e-10
#define N 500020
#define B 20
#define M 3000020
#define inf 0x3f3f3f3f
#define LL long long
#define pii pair<int, int>
#define MP make_pair
#define fi first
#define se second
#define mod 1000007

#define md (ll + rr >> 1)

struct state {
	int a[21], cnt;
	bool operator < (const state &b) const {
		return cnt < b.cnt;
	}
}st[N];
int f[1000007];

int tot;
double p[N];
int n;
vector<int> s[N];
int b[N];
double dp[21][700];
double g[22][22], X[22];
int tr[700][22][22];

void dfs(int k, int mx, int sum) {
	if(sum == n) {
		++tot;
		for(int i = 1; i < k; ++i) {
			st[tot].a[i] = b[i];
		}
		st[tot].cnt = k - 1;
		return;
	}
	for(int i = mx; i <= n - sum; ++i) {
		if(!(n - sum - i == 0 || n - sum - i >= i)) continue;
		b[k] = i;
		dfs(k + 1, i, sum + i);
	}
}

int code(state &t) {
	int ret = t.cnt;
	for(int i = 1; i <= t.cnt; ++i) {
		ret = 1LL * ret * 233 % mod + t.a[i];
		ret %= mod;
	}
	return ret;
}

int merge(state t, int x, int y) {
	t.a[x] += t.a[y];
	swap(t.a[y], t.a[t.cnt]);
	t.cnt--;
	sort(t.a + 1, t.a + t.cnt + 1);
	return f[code(t)];
}

int sgn(double x) {
	if(fabs(x) < eps) return 0;
	return x < 0? -1: 1;
}

void gauss() {
	for(int i = 1; i <= n; ++i) {
		int u = -1;
		for(int v = i; v <= n; ++v) {
			if(u == -1 || fabs(g[v][i]) > fabs(g[u][i])) u = v;
		}
		if(u == -1 || sgn(g[u][i]) == 0) {
			puts("error");
			exit(0);
		}
		for(int x = i; x <= n + 1; ++x) swap(g[i][x], g[u][x]);
		for(int x = i + 1; x <= n; ++x) {
			if(sgn(g[x][i])) {
				double tmp = g[x][i] / g[i][i];
				for(int k = i; k <= n + 1; ++k) {
					g[x][k] -= g[i][k] * tmp;
				}
			}
		}
	}

	for(int i = n; i >= 1; --i) {
		X[i] = g[i][n+1];
		for(int j = i + 1; j <= n; ++j) X[i] -= g[i][j] * X[j];
		X[i] /= g[i][i];
	}
}


void get_data() {
	freopen("tt.txt", "w", stdout);
	int t = 19;
	printf("1\n%d\n", t);
	for(int i = 1; i <= t; ++i) printf("%.3lf ", 0.5);
	for(int i = 1; i <= t; ++i) {
		printf("%d ", t);
		for(int j = 1; j <= t; ++j) printf("%d ", j);
		puts("");
	}
	exit(0);
}
	

int main() {
//	get_data();
//	freopen("tt.txt", "r", stdin);
	int cas, kk = 0;
	scanf("%d", &cas);
	while(cas--) {
		scanf("%d", &n);
		for(int i = 1; i <= n; ++i) scanf("%lf", &p[i]), s[i].clear();
		for(int i = 1; i <= n; ++i) {
			int t, x;
			scanf("%d", &t);
			while(t--) {
				scanf("%d", &x);
				s[i].push_back(x);
			}
		}
		tot = 0;
		dfs(1, 1, 0);
		sort(st + 1, st + tot + 1);
		for(int i = 1; i <= tot; ++i) {
			f[code(st[i])] = i;
		}
		for(int i = 1; i <= n; ++i) dp[i][1] = 0;
		for(int i = 2; i <= tot; ++i) {
			for(int x = 1; x <= st[i].cnt; ++x) {
				for(int y = x + 1; y <= st[i].cnt; ++y) {
					tr[i][x][y] = merge(st[i], x, y);
				}
			}
		}
		for(int i = 2; i <= tot; ++i) {
			memset(g, 0, sizeof g);
			for(int u = 1; u <= n; ++u) {
				double right = 1;
				for(int x = 1; x <= st[i].cnt; ++x) {
					for(int y = x + 1; y <= st[i].cnt; ++y) {
						double tmp = st[i].a[x] * st[i].a[y];
						tmp = tmp / (n * (n - 1) / 2) / s[u].size() * p[u];
						int id = tr[i][x][y];
						for(int zz = 0; zz < s[u].size(); ++zz) {
							int z = s[u][zz];
							right += dp[z][id] * tmp;
					//		if(st[id].cnt == 1) right -= tmp;
						}
					}
				}
				g[u][n+1] = right;
				g[u][u] = 1;
				double tmp = 0;
				for(int x = 1; x <= st[i].cnt; ++x) tmp += st[i].a[x] * (st[i].a[x] - 1) / 2;
				tmp = tmp * p[u] / (n * (n - 1) / 2) / s[u].size();
				for(int x = 0; x < s[u].size(); ++x) {
					int v = s[u][x];
					g[u][v] -= tmp;
				}
				tmp = (1 - p[u]) / s[u].size();
				for(int x = 0; x < s[u].size(); ++x) {
					int v = s[u][x];
					g[u][v] -= tmp;
				}
			}
			gauss();
			for(int j = 1; j <= n; ++j) dp[j][i] = X[j];
		}
		printf("Case #%d: %.6f\n", ++kk, dp[1][tot]);
	}
	return 0;
}

hdu 4936 Rainbow Island (状压dp+高斯消元)

标签:

原文地址:http://blog.csdn.net/u013654696/article/details/51332057

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!