【題解】 bzoj1076: [SCOI2008]獎勵關 (裝壓+期望dp)
阿新 • • 發佈:2018-07-23
狀態 span 方程 con can i+1 std tin log
題面戳我
Solution
- 並不會做,看了下題解大概了解了。期望這個東西好難搞啊qwq
- 我們定義\(dp[i][j]\)表示第\(i\)步,拿到寶物前的狀態為\(j\)。
- 正著來會有很多不合法的情況,剔除比較麻煩,我們反著來考慮,因為你想如何是合法,就是狀態表示拿得物品個數小於等於步數嘛,倒著來最後答案根據我們狀態定義可以知道,答案是\(dp[1][0]\)嘛,然後你想,我們每向前一次,就最多剔除一個寶物,最多剔除的就是\(K\)個,其余不合法的情況到最後不會剔除完,就不會被計入答案中
- 轉移方程是\[dp[i][j]=dp[i][j]+\Sigma_{k=1}^n max(dp[i+1][j],dp[i+1][j|(sta[k])+s[k]])/n\]
- 不然轉移方程就是\[dp[i][j]=dp[i][j]+dp[i+1][j]/n\]
- 多做幾道期望dp,感受下吧qwq
Code
//It is coded by ning_mew on 7.21 #include<bits/stdc++.h> #define db double using namespace std; const int maxk=105,maxn=20; int n,K; int sta[maxn],s[maxn]; db dp[maxk][(1<<15)+100]; int main(){ scanf("%d%d",&K,&n); for(int i=1;i<=n;i++){ int box=0; scanf("%d",&s[i]); while(1){ scanf("%d",&box);if(!box)break; sta[i]=(sta[i]|(1<<(box-1))); } } for(int i=K;i>=1;i--){ for(int j=0;j<=(1<<n)-1;j++){ for(int k=1;k<=n;k++){ if((sta[k]&j)!=sta[k]){dp[i][j]=dp[i][j]+dp[i+1][j]/n;continue;} dp[i][j]=dp[i][j]+1.0*max(dp[i+1][j],dp[i+1][j|(1<<(k-1))]+s[k])/n; } } }printf("%0.6f\n",dp[1][0]);return 0; }
博主蒟蒻,隨意轉載。但必須附上原文鏈接:http://www.cnblogs.com/Ning-Mew/,否則你會場場比賽暴0!!!
【題解】 bzoj1076: [SCOI2008]獎勵關 (裝壓+期望dp)