題目大意:有$m$個人要從城市$1$開始,依次遊覽城市$1$到$n$。
每一天,每乙個遊客有$p_i$的概率去下乙個城市,和$1-p_i$的概率結束遊覽。
當遊客到達城市$j$,他會得到$(1+\frac})h_$的收益,其中$c_i$表示到訪第$i$個城市的人數。
問所有人的期望收益。
資料範圍:$n,m≤16$
我們考慮狀壓$dp$
設$f[i][s]$表示到達城市i的人群為$s$的概率。
設$ans[i][s]$表示到達城市i的人群為$s$時,所有人在前$i$座城市的收益和。
不難推出:
$f[i][s]=\sum\limits_ f[i-1][p]\times chg(p,s)$
$ans[i][s]=\sum\limits_ \big(ans[i-1][p]+f[i-1][p]\times sum[i][s]\times (1+\frac)\big)\times chg(p,s)$
其中,$chg(p,s)$表示前一次遊覽的人群為$p$,下一次剩下$s$的概率。簡單乘一下就行了。
這麼轉移的複雜度是$o(n\times 3^m)$的,然而他t了。。。。
1 #include2#define m 16
3#define get orzmyh
4using
namespace
std;56
int m,n,all=0;7
8double p[m+1]=,h[m+1][m+1]=,mulp[1
<0},fmulp[1
<0};9
double f[m+1][1
<0},ans[m+1][1
<0},mo[1
<0},sum[m+1][1
<0
};10
11double get(int p,int
s)14
double sum(int day,int
s)19
return
res;20}
2122
intmain()
34 mulp[i]=mul1;
35 fmulp[i]=mul2;36}
3738
for(int i=0;i)
39for(int j=1;j<=n;j++)
40 scanf("
%lf",&h[i][j]);
4142
for(int i=1;i<=n;i++)
46 f[1][all-1]=1; ans[1][all-1]=sum[1][all-1
];47
for(int i=2;i<=n;i++)55}
56double ans=0;57
for(int s=0;s)
58 ans+=ans[n][s];
59 printf("
%.10lf\n
",ans);
60 }
於是我後來寫了乙個$o(nm\times 2^m)$的,**如下:
1 #include2#define m 17
3using
namespace
std;45
double f[m][m]=,h[m][m]=,p[m]=;
6int
n,m;78
intmain()
16double ans=0;17
for(int i=1;i<=m;i++)22}
23for(int i=1;i)else ps*=1-f[j][i];
3132
for(int j=1;j<=m;j++) if(s&(1
<<(j-1
)))33 sum+=p[j]*h[j][i+1]*(pn-p[j]+1
);34 ans+=ps*sum/cnt;35}
36}37 printf("
%.10lf\n
",ans);
38 }
簡單的期望 狀壓dp
dp定義真的神,直接的想法是 f x maxn 為第 x 個操作,狀態 maxn maxn 1 200,好像沒有暴力分高 實際上我們可以這樣定義 f x maxn len 0 1 表示後八位 maxn 第九位0 1,第九位之後連續長度為 j 概率 為什麼這樣定義 實際上質因數分解後2的次數就是後面0...
bzoj 1076(狀壓dp)(期望dp)
傳送門 題解 dp i j 表示第i輪狀態為j 狀態中為1的位表示當前物品還沒被取走 的最大期望得分。為了防止從無效狀態轉移至有效狀態,採用倒推法,從已知的有效狀態往回推,具體注釋在 中。p.s.不寫memset可以快接近一倍,但是為了思維嚴密性,還是寫乙個,反正都能過 注意 由於吃過的寶物可以再吃...
狀壓DP《旅行商問題》
旅行社問題就是給乙個有向圖,從點0走一圈全部結點再走回來所花費的費用最少是多少。狀壓dp一般n 15。因為是走完全部點,那麼走到2點的費用有可能走了5,也可能沒走,那麼就不能簡單的用最短路來找。因為要求跑完全部點回到0,而最小樹形圖的話無法做到。狀壓dp是指在乙個點上存在多種狀態,這些狀態可以用二進...