你正在玩你最喜歡的電子遊戲,而且剛剛進入一個獎勵關。在這個獎勵關裏,系統將依次隨機拋出k次寶物,
每次你均可以選擇吃或者不吃(必須在拋出下一個寶物以前作出選擇,且如今決定不吃的寶物之後也不能再吃)。
寶物一共有n種,系統每次拋出這n種寶物的機率都相同且相互獨立。也就是說,即便前k-1次系統都拋出寶物1(
這種狀況是有可能出現的,儘管機率很是小),第k次拋出各個寶物的機率依然均爲1/n。 獲取第i種寶物將獲得Pi
分,但並非每種寶物都是能夠隨意獲取的。第i種寶物有一個前提寶物集合Si。只有當Si中全部寶物都至少吃過
一次,才能吃第i種寶物(若是系統拋出了一個目前不能吃的寶物,至關於白白的損失了一次機會)。注意,Pi可
以是負數,但若是它是不少高分寶物的前提,損失短時間利益而吃掉這個負分寶物將得到更大的長期利益。 假設你
採起最優策略,平均狀況你一共能在獎勵關獲得多少分值?c++
第一行爲兩個正整數k和n,即寶物的數量和種類。如下n行分別描述一種寶物,其中第一個整數表明分值,隨
後的整數依次表明該寶物的各個前提寶物(各寶物編號爲1到n),以0結尾。spa
輸出一個實數,保留六位小數,即在最優策略下平均狀況的得分。code
1 2
1 0
2 0遊戲
1.500000ip
【數據規模】input
1<=k<=100,1<=n<=15,分值爲\([-10^6,10^6]\)內的整數。it
正着考慮是很差計算的io
因此就能夠反着考慮class
而後每次枚舉第i次獎勵以前的狀態和當前獎勵的物品而後選取最優值就能夠了數據
每次算的時候須要除以方案數n
#include<bits/stdc++.h> using namespace std; const int N = (1 << 15) + 10; const int K = 110; int pre[N], n, k; double p[N], dp[K][N]; int main() { scanf("%d %d", &k, &n); for (int i = 1; i <= n; i++) { scanf("%lf", &p[i]); int u; scanf("%d", &u); while (u) { pre[i] |= 1 << (u - 1); scanf("%d", &u); } } int up = 1 << n; for (int i = k; i >= 1; i--) { for (int s = 0; s < up; s++) { for (int j = 1; j <= n; j++) { if ((s & pre[j]) == pre[j]) { dp[i][s] += max(dp[i + 1][s], dp[i + 1][s | (1 << (j - 1))] + p[j]); } else { dp[i][s] += dp[i + 1][s]; } } dp[i][s] /= (double) n; } } printf("%.6lf", dp[1][0]); return 0; }