BZOJ1076:[SCOI2008]獎勵關——題解
http://www.lydsy.com/JudgeOnline/problem.php?id=1076
https://www.luogu.org/problemnew/show/P2473
你正在玩你最喜歡的電子遊戲,並且剛剛進入一個獎勵關。在這個獎勵關裏,系統將依次隨機拋出k次寶物,每次你都可以選擇吃或者不吃(必須在拋出下一個寶物之前做出選擇,且現在決定不吃的寶物以後也不能再吃)。
寶物一共有n種,系統每次拋出這n種寶物的概率都相同且相互獨立。也就是說,即使前k-1 次系統都拋出寶物1(這種情況是有可能出現的,盡管概率非常小),第k次拋出各個寶物的概率依然均為1/n。
獲取第 i 種寶物將得到Pi分,但並不是每種寶物都是可以隨意獲取的。第i種寶物有一個前提寶物集合Si。只有當Si中所有寶物都至少吃過一次,才能吃第i 種寶物(如果系統拋出了一個目前不能吃的寶物,相當於白白的損失了一次機會)。註意,Pi 可以是負數,但如果它是很多高分寶物的前提,損失短期利益而吃掉這個負分寶物將獲得更大的長期利益。
假設你采取最優策略,平均情況你一共能在獎勵關得到多少分值?
因為自己的期望太垃圾於是主動找期望題刷。
結果同時碰上了自己不太會的狀壓。
寫就寫,誰怕誰。
————————————
先想暴力,顯然枚舉最後狀態不斷往前dfs得到最優解即可。
轉標程,打眼一看n很小,直接想到狀壓f[i][j]表示第i次拋物品後狀態為j。
但是為了滿足最優解我們只能從後往前推,即改為f[i][j]表示第i次拋物品,此時狀態為j時往後做能得到的最大期望分數。
於是從後往前推即可。
顯然滿足條件的時候我們可以選擇(不取該物品的期望)或(取該物品的期望+該物品價值)。
當不滿足條件的時候我們只可選前者。
因為是期望所以答案是累加進f數組的,最後除n即可。
#include<cmath> #include<cstdio> #include<cctype> #include<cstring> #include<iostream> #include<algorithm> using namespace std; typedef double dl; constint N=32768; inline int read(){ int X=0,w=0;char ch=0; while(!isdigit(ch)){w|=ch==‘-‘;ch=getchar();} while(isdigit(ch))X=(X<<3)+(X<<1)+(ch^48),ch=getchar(); return w?-X:X; } dl f[101][N],v[16]; int k,n,t[16]; int main(){ k=read(),n=read(); for(int i=1;i<=n;i++){ v[i]=read(); int ch=read(); while(ch){ t[i]=t[i]|(1<<ch>>1); ch=read(); } } for(int i=k;i>=1;i--){ for(int l=0;l<=(1<<n);l++){ for(int j=1;j<=n;j++){ int h=1<<j>>1; if((l&t[j])==t[j]){ f[i][l]+=max(f[i+1][l],f[i+1][l|h]+v[j]); }else f[i][l]+=f[i+1][l]; } f[i][l]/=n; } } printf("%.6lf\n",f[1][0]); return 0; }
+++++++++++++++++++++++++++++++++++++++++++
+本文作者:luyouqi233。 +
+歡迎訪問我的博客:http://www.cnblogs.com/luyouqi233/+
+++++++++++++++++++++++++++++++++++++++++++
BZOJ1076:[SCOI2008]獎勵關——題解