zoj3822Domination 概率dp

//一个n*m的棋盘
//每次在棋盘上没放子的位置等概率地放子
//问使得棋盘上的每一行和每一列至少有一个子的放子的期望
//dp[i][j][k] 表示剩下k个空白位置 ,i个空白行 , j个空白列的期望
//那么这一次放子有四种情况
//1:放在空白行和空白列的概率p1 = i*j*/k
//2:放在空白行不是空白列的概率p2 = (m*i-i*j)/k
//3:放在空白列不是空白行的概率p3 = (n*j - i*j)/k
//4:放的既不是空白行也不是空白列的概率p4 = (k - (m*i+n*j-i*j))/k
#include<cstdio>
#include<cstring>
#include<iostream>
using namespace std ;
const int maxn = 60 ;
double dp[maxn][maxn][maxn*maxn] ;
int main()
{
    int n , m ;
    int t ;
    scanf("%d" , &t) ;
    while(t--)
    {
        scanf("%d%d" , &n , &m) ;
        memset(dp , 0 , sizeof(0))  ;
        for(int k = 1;k <= n*m ;k++)
          for(int i = 0;i <= n;i++)
            for(int j = 0;j <= m;j++)
            {
                if(m*i > k || n*j > k || (!i && !j))
                continue ;
                double tmp1 = (i > 0 && j > 0) ? i*j*1.0/k*dp[i-1][j-1][k-1] : 0 ;
                double tmp2 = (i > 0)? (m*i-i*j)*1.0/k*dp[i-1][j][k-1] : 0;
                double tmp3 = (j > 0)? (n*j - i*j)*1.0/k*dp[i][j-1][k-1] : 0 ;
                double tmp4 = (k - (m*i+n*j-i*j))*1.0/k*dp[i][j][k-1] ;
                dp[i][j][k] = tmp1 + tmp2 + tmp3 + tmp4 + 1 ;
            }
        printf("%.8lf\n" , dp[n][m][n*m]) ;
    }
    return 0 ;
}


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