zoj 3822 Domination (概率dp 天数期望)
参考博客:http://blog.csdn.net/napoleon_acm/article/details/40020297
题意:给定n*m的空棋盘
每一次在上面选择一个空的位置放置一枚棋子,直至每一行每一列都至少有一个棋子,求放置次数的期望
分析:
dp[i][j][k] 表示当前用了<=k个chess ,覆盖了i行j列(i*j的格子 每行至少一个,每列至少一个)的概率。
dp[i][j][k] 由 dp[i][j][k-1] , dp[i-1][j][k-1], dp[i][j-1][k-1], dp[i-1][j-1][k-1]得到,分别表示 添加的新的一个chess, 不覆盖新的行列, 只新覆盖一行, 只新覆盖一列, 同时新覆盖一行和一列,得到dp[i][j][k]。
递推时, 每个概率 * (可以覆盖的点数/剩余所有的空点数) 相加得到[i][j][k].
ans += (dp[n][m][i] - dp[n][m][i-1])* i; (i = [1, n*m])
1 #include <iostream> 2 #include <cstdio> 3 #include <cstring> 4 #include <cstdlib> 5 #include <cmath> 6 #include <algorithm> 7 #define LL __int64 8 const int maxn = 50+10; 9 using namespace std; 10 double d[maxn][maxn][2600]; 11 12 int main() 13 { 14 double ans; 15 int t, i, j, k, n, m; 16 cin>>t; 17 while(t--) 18 { 19 cin>>n>>m; 20 memset(d, 0, sizeof(d)); 21 d[0][0][0] = 1; 22 for(i = 1; i <= n; i++) 23 for(j = 1; j <= m; j++) 24 for(k = 1; k <= n*m; k++) 25 { 26 int sum = n*m-k+1; 27 d[i][j][k] = d[i][j][k-1]*((i*j-k+1)*1.0/sum*1.0)+ //因为这里还加上了已经覆盖了i行j列的概率,所以dp[i][j][k] 表示当前用了<=k个chess ,覆盖了i行j列(i*j的格子 每行至少一个,每列至少一个)的概率。 28 d[i-1][j][k-1]*(j*(n-i+1)*1.0/sum*1.0)+ 29 d[i][j-1][k-1]*(i*(m-j+1)*1.0/sum*1.0)+ 30 d[i-1][j-1][k-1]*((n-i+1)*(m-j+1)*1.0/sum*1.0); 31 } 32 ans = 0; 33 for(i = 1; i <= n*m; i++) 34 ans += (d[n][m][i]-d[n][m][i-1])*i; //减去表示用i个棋子覆盖的概率。 35 36 printf("%.12lf\n", ans); 37 } 38 return 0; 39 }
做了后一道概率dp,发现也可以用期望你逆推的方法。
可参照博客:http://blog.csdn.net/smz436487/article/details/40049189
初始化:dp[i][n][m]=0;(0<=i<=n*m)
dp[0][0][0]就是答案。
2维的没办法描述每种状态下的概率
代码:
1 #include <iostream> 2 #include <cstring> 3 #include <cstdio> 4 using namespace std; 5 double dp[2505][55][55]; 6 int main() 7 { 8 int t,n,m; 9 scanf("%d",&t); 10 while(t--){ 11 scanf("%d%d",&n,&m); 12 memset(dp,0,sizeof(dp)); 13 for(int i=n*m-1;i>=0;i--){ 14 for(int j=n;j>=0;j--){ 15 for(int k=m;k>=0;k--){ 16 if(j==n&&k==m)continue; 17 if(j*k<i)continue; 18 double p1,p2,p3,p4; 19 p1=1.0*(j*k-i)/(n*m-i); 20 p2=1.0*(n-j)*k/(n*m-i); 21 p3=1.0*(m-k)*j/(n*m-i); 22 p4=1.0*(n-j)*(m-k)/(n*m-i); 23 dp[i][j][k]=dp[i+1][j][k]*p1+dp[i+1][j+1][k]*p2+dp[i+1][j][k+1]*p3+dp[i+1][j+1][k+1]*p4+1; 24 } 25 } 26 } 27 printf("%.10lf\n",dp[0][0][0]); 28 } 29 return 0; 30 }