标签:
#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