zoj3822(概率dp)

链接:点击打开链接

题意:一个n行m列的棋盘,每次放一个棋子,问要使得棋盘的每行每列都至少有一个棋子,需要的放棋子次数的期望

代码:

#include <queue>
#include <vector>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <iostream>
#include <algorithm>
using namespace std;
double dp[55][55][3005];
int main(){
    double ans;
    int n,m,i,j,k,t;
    scanf("%d",&t);
    while(t--){
        scanf("%d%d",&n,&m);
        memset(dp,0,sizeof(dp));
        dp[1][1][1]=1;                          //dp[i][j][k]表示用不大于k个棋子占据i行j列时的概率的和
        for(k=2;k<=n*m;k++)
        for(i=1;i<=n;i++)
        for(j=1;j<=m;j++){                      //每个状态可由四个状态推出
            dp[i][j][k]+=dp[i][j][k-1]*(i*j-k+1)/(n*m-k+1);
            dp[i][j][k]+=dp[i][j-1][k-1]*i*(m-j+1)*1.0/(n*m-k+1);
            dp[i][j][k]+=dp[i-1][j][k-1]*(n-i+1)*j*1.0/(n*m-k+1);
            dp[i][j][k]+=dp[i-1][j-1][k-1]*(n-i+1)*(m-j+1)*1.0/(n*m-k+1);
        }
        ans=0;
        for(i=1;i<=n*m;i++){
        ans+=(dp[n][m][i]-dp[n][m][i-1])*i;
//        cout<<dp[n][m][i]*i<<endl;
        }
        printf("%.12lf\n",ans);
    }
    return 0;
}


 

你可能感兴趣的:(zoj3822(概率dp))