zoukankan      html  css  js  c++  java
  • ZOJ 3822 ( 2014牡丹江区域赛D题) (概率dp)

    http://acm.zju.edu.cn/onlinejudge/showProblem.do?problemId=5376

    题意:每天往n*m的棋盘上放一颗棋子,求多少天能将棋盘的每行每列都至少有一颗棋子的期望

     

    分析: 我们来分析一波; 讲解一下弱弱的我的解题思路

    (1)首先可以想到的是设一个 dp[val]  表示 当前用了val 个旗子距离目标状态还有几天的概率。但是我们可以发现单纯的一个状态val 是不能表示出准确的状态 , 比如说现在只是知道了我使用了多少的旗子,当前不知道有多少行和列是有旗子的;

    (2)所以我们改变dp为 dp[val][i][j]  表示 用了val个旗子,有i行和j列有旗子了,到目标状态还有几天的概率。注意我们设的是概率dp[val][i][j] 有一个状态是val天数了 , 所以3我们可以先把概率求出来,最后在计算期望

    (3)状态转移:有四种状态

    (1)加入一个是放在记录的行中与列中:dp[val+1][i][j] -> dp[val][i][j] *p1;

    (2)加入一个是放在没有记录过的行中与记录过的列中: dp[val+1][i+1][j] -> dp[val][i][j]*p2;

    (3)加入一个是放在记录过的行中与没有记录过的列中:dp[val+1][i][j+1]->dp[val][i][j]*p3;

    (4)加入一个是放在没有记录的行中与没有记录过的列中:dp[val+1][i+1][j+1]->dp[val][i][j]*p4;

    p1,p2,p3,p4求法可以观察下图:

    图中红色部分可视为j行k列已经至少有一个棋子了

    #include<bits/stdc++.h>
    using namespace std;
    double dp[2501][51][51];
    int main() {
        int t;
        cin >> t;
        int k=1;
        while(t--) {
          int n,m;scanf("%d%d",&n,&m);
          memset(dp,0,sizeof(dp));
          dp[1][1][1]=1;
          for(int val=1 ; val<n*m ; val++) ///放其
          {
              for(int i=1 ; i<=n ; i++)
                {
                    for(int j=1 ; j<=m ; j++)
                    {
                        if(dp[val][i][j]==0) continue;
                        double p1,p2,p3,p4;
                        if( i<n  ||j<m){
                        p1=(i*j-val)*1.0/(n*m-val);
                        dp[val+1][i][j]+=dp[val][i][j]*p1;
                        }
                        p2=j*(n-i)*1.0/(n*m-val);
                        dp[val+1][i+1][j]+=dp[val][i][j]*p2;
                        p3=i*(m-j)*1.0/(n*m-val);
                        dp[val+1][i][j+1]+=dp[val][i][j]*p3;
                        p4=(n-i)*(m-j)*1.0/(n*m-val);
                        dp[val+1][i+1][j+1]+=dp[val][i][j]*p4;
    
                    }
                }
          }
          double ans=0;
          for(int val=1 ; val<=n*m ; val++)
          {
              ans+=dp[val][n][m]*val;
              //cout<<dp[val][n][m]<<endl;
          }
          printf("%.12f
    ",ans);
    
        }
        return 0;
    }
    View Code
  • 相关阅读:
    在 macOS High Sierra 10.13 搭建 PHP 开发环境
    给你的网站免费配置上 HTTPS 证书
    将 MacOS 默认的 PHP 版本升级到 7.*
    System.Data.SqlClient.SqlException: 'Incorrect syntax near 'OFFSET'.
    IIS7/8 HTTP Error 500.19 错误 0x80070021 错误代码:0x8007000d
    http error 502.5
    信用卡逾期了怎么办 ?逾期记录“修复”的两大原则
    APP多开教程
    lua调用不同lua文件中的函数
    Lua 用指定字符或字符串分割输入字符串,返回包含分割结果的数组
  • 原文地址:https://www.cnblogs.com/shuaihui520/p/11165758.html
Copyright © 2011-2022 走看看