nssl1468-V【状压,数学期望,dfs】
生活随笔
收集整理的這篇文章主要介紹了
nssl1468-V【状压,数学期望,dfs】
小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
正題
題目大意
nnn個球排成一排顏色不同,每次選擇一個隨機的[1..n][1..n][1..n]中的xxx,然后刪掉第xxx個或第n?x+1n-x+1n?x+1個數,求刪kkk次之后刪掉的白球最多,求刪掉數量的期望值
解題思路
考慮狀態壓縮dpdpdp,定義第一個111所在位數表示剩下的球數,111表示該位置是白球,000表示該位置是黑球。設fsf_sfs?表示狀態為sss時的最小期望值。
del(s,i)del(s,i)del(s,i)表示sss去掉第iii個球后的狀態,有狀態轉移方程fs=∑i=1lmax{fdel(s,i)+one(s,i),fdel(s,n?i+1)+one(s,n?i+1)}lf_s=\frac{\sum_{i=1}^lmax\{f_{del(s,i)}+one(s,i),f_{del(s,n-i+1)}+one(s,n-i+1)\}}{l}fs?=l∑i=1l?max{fdel(s,i)?+one(s,i),fdel(s,n?i+1)?+one(s,n?i+1)}?
這樣的時間復雜度為O(2nn)O(2^nn)O(2nn)
但是有許多狀態是沒有使用的,我們對于小的sss可以用一個桶存,對于大的sss我們可以用mapmapmap來存即可
codecodecode
#include<cstdio> #include<cstring> #include<algorithm> #include<map> #define XJQ using #define AK namespace #define IOI std XJQ AK IOI; const int N=35,Lim=1<<24; int n,k; double a[Lim]; map<int,double> m; char str[N]; bool live(int x,int l){int z=x|(1<<l);if(z<Lim)return (a[z]!=-1);return m.count(z); } double get(int x,int l){int z=x|(1<<l);if(z<Lim)return a[z];return m[z]; } void change(int x,int l,double val){int z=x|(1<<l);if(z<Lim) a[z]=val;else m[z]=val;return; } int del(int x,int w) {return ((x>>w+1)<<w)+x%(1<<w);} double dfs(int s,int l){if(l<=n-k)return 0;if(live(s,l))return get(s,l);double ans=0;for(int i=0;i<l;i++) ans+=(max(dfs(del(s,i),l-1)+((s>>i)&1),dfs(del(s,l-i-1),l-1)+((s>>(l-i-1))&1)))/l;change(s,l,ans);return ans; } int main() {scanf("%d%d",&n,&k);scanf("%s",str);int s=0;for(int i=0;i<Lim;i++)a[i]=-1;for(int i=0;i<n;i++)s|=((str[i]=='W')<<i);printf("%.6lf",dfs(s,n)); }總結
以上是生活随笔為你收集整理的nssl1468-V【状压,数学期望,dfs】的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 2021年11月最真实的电脑购买指南20
- 下一篇: nssl1469-W【dp】