ZOJ 3822 Domination 概率DP 2014年ACM_ICPC亚洲区域赛牡丹江现场赛D题

题目大意:

就是现在有一个N*M的棋盘(1 <= N, M <= 50)每次在上面的空位置随机选一个放一个棋子, 问使得所有行和所有列上都有棋子放置, 放置的棋子的数目期望


大致思路:

这题同步赛的时候没感觉, 现在做发现就是一个水题, 当时还是太弱了...

状态转移方程见代码注释吧..


代码如下:

Result  :  Accepted     Memory  :  51276 KB     Time  :  1750 ms

/*
 * Author: Gatevin
 * Created Time:  2014/12/23 20:26:43
 * File Name: Sora_Kasugano.cpp
 */
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
using namespace std;
const double eps(1e-8);
typedef long long lint;

/*
 * 用dp[i][j][k]表示对于N*M的棋盘, 已经用k个子占了i行和j列时到达目标状态需要的chess piece数量期望
 * 那么显然dp[N][M][min(N, M)~N*M] = 0, 状态转移方程:
 * dp[i][j][k] =  (N - i)*(M - j)/(N*M - k)*(dp[i + 1][j + 1][k + 1] + 1)
 *              + (N - i)*j/(N*M - k)*(dp[i + 1][j][k + 1] + 1)
 *              + i*(M - j)/(N*M - k)*(dp[i][j + 1][k + 1] + 1)
 *              + (i*j - k)/(N*M - k)*(dp[i][j][k + 1] + 1)
 * 考虑一下边界条件即可, dp[0][0][0]即为答案
 */

/*
 * 牡丹江那场区域赛在同步赛场外做的时候没思路, 现在一看的确是个水题..当时还是太弱了
 */

double dp[51][51][2510];

int main()
{
    int t;
    scanf("%d", &t);
    int N, M;
    while(t--)
    {
        scanf("%d %d", &N, &M);
        memset(dp, 0, sizeof(dp));
        for(int i = N; i >= 0; i--)
            for(int j = M; j >= 0; j--)
            {
                if(i == N && j == M) continue;
                for(int k = i*j; k >= min(i, j); k--)
                {
                    dp[i][j][k] = 0;
                    if(i + 1 <= N && j + 1 <= M && (i + 1)*(j + 1) >= k + 1)
                        dp[i][j][k] += (N -i)*(M - j)*1.0/(N*M - k)*(dp[i + 1][j + 1][k + 1] + 1);
                    if(i + 1 <= N && (i + 1)*j >= k + 1)
                        dp[i][j][k] += (N - i)*j*1.0/(N*M - k)*(dp[i + 1][j][k + 1] + 1);
                    if(j + 1 <= M && (j + 1)*i >= k + 1)
                        dp[i][j][k] += i*(M - j)*1.0/(N*M - k)*(dp[i][j + 1][k + 1] + 1);
                    if(i*j >= k + 1)
                        dp[i][j][k] += (i*j - k)*1.0/(N*M - k)*(dp[i][j][k + 1] + 1);
                }
            }
        printf("%.8f\n", dp[0][0][0]);
    }
    return 0;
}


你可能感兴趣的:(ACM_Probability,ZOJ)