HDU 4921 Map

weixin_30924079發表於2020-04-04

題意:

給n個節點  他們形成了最多10條鏈  每條最多1000的長度  每一個節點有個val  你能夠選擇任何位置截斷鏈  斷點前的全部節點被你獲得  通過題中計算公式得出你的val  問  通過隨機截斷  獲得val的期望是多少

思路:

期望=全部方案val的和/方案數

這裡明顯有分層的現象  並且每層最多10個元素  因此想到狀壓  那麼我們僅僅要逐層統計  每層計算一下能對“全部方案val的和”產生多少貢獻就可以  方案數能夠直接算出來  計算方法例如以下

對於方案數  它就等於 (amt[1]+1)*(amt[2]+1)*…  amt[i]為每條鏈上的節點總數  這個式子就表示對於每條鏈有amt+1種截斷方式  即  一開始就截斷+在每一個元素後面截斷

對於val的和  我們通過每層的狀態來計算(剛才也說了要狀態壓縮)

假設狀壓中該位置為1表示選中該元素  那麼序列一定是這種111111XXXXXX  即1前面一定都是1  因此相應的方案有amt-層數+1 種

假設該位置為0  那麼序列一定是這種 XXXXXXX000000 即0後面一定都是0  那麼方案就有 層數 種

知道了那一層所形成的方案數  那麼僅僅須要計算一下該層的節點val和與方案數乘一下就能夠了

程式碼:

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
#define N 10010

int next[N], vis[N], val[N], amt[10], qu[10];
double x, y;
int t, n, m, tot;

int main() {
	int i, u, v, floor, have, num;
	double ways, res;
	//freopen("1001.in", "r", stdin);
	//freopen("1001.out", "w", stdout);
	scanf("%d", &t);
	while (t--) {
		scanf("%d%d", &n, &m);
		memset(next, 0, sizeof(next));
		memset(vis, 0, sizeof(vis));
		memset(amt, 0, sizeof(amt));
		tot = 0;
		x = 1;
		y = 0;
		for (i = 1; i <= n; i++)
			scanf("%d", &val[i]);
		for (i = 1; i <= m; i++) {
			scanf("%d%d", &u, &v);
			u++;
			v++;
			next[u] = v;
			vis[v] = 1;
		}
		for (i = 1; i <= n; i++)
			if (!vis[i]) {
				qu[tot] = i;
				for (u = i; u; u = next[u])
					amt[tot]++;
				x *= amt[tot] + 1;
				tot++;
			}
		for (floor = 1;; floor++) {
			num = 0;
			for (i = 0; i < tot; i++)
				if (qu[i])
					num++;
			if (!num)
				break;
			for (u = 1; u < (1 << tot); u++) {
				have = 0;
				ways = 1;
				res = 0;
				for (i = 0; i < tot; i++) {
					if (u & (1 << i)) {
						if (!qu[i])
							break;
						res += val[qu[i]];
						have++;
						ways *= amt[i] - floor + 1;
					} else
						ways *= min(floor, amt[i] + 1);
				}
				if (i == tot) {
					y += res * ways;
					if (have > 1)
						y += res * have * ways / num;
				}
			}
			for (i = 0; i < tot; i++)
				qu[i] = next[qu[i]];
		}
		//printf("%.3f %.3f  ", y, x);
		printf("%.3f\n", y / (x - 1));
	}
	return 0;
}


轉載於:https://www.cnblogs.com/yxwkf/p/4042460.html