zoukankan      html  css  js  c++  java
  • 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
    ", 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
    ",dp[0][0][0]);
    28     }
    29     return 0;
    30 }
  • 相关阅读:
    【2】通过Ajax方式上传文件(图片),使用FormData进行Ajax请求
    【1】mongoDB 的安装及启动
    第一篇博客
    Java Integer 进制转化的实现(附源码),对模与补码的理解
    筛法求素数(普通筛法与欧拉筛法) 这是个问题
    字典的拼接方法
    使用Selenium抓取百度指数一
    正则表达式30分钟入门教程
    微博抓取尝试
    __call__方法的最简要说明
  • 原文地址:https://www.cnblogs.com/bfshm/p/4023046.html
Copyright © 2011-2022 走看看