ZOJ 3822 Domination(2014牡丹江Regional D题)

人家当场切掉的题,表示在场外做zoj还是要别人提醒dp数组的i,j,k分别表示什么含义才能AC...

下周鞍山之行无限堪忧TAT~

题目大意:有一个n * m的棋盘,每天放入一个棋子,当所有行和列都存在棋子的时候,就是一种符合的情况。

然后这种情况的值就是它的天数(也就是棋子个数),问所有符合的情况的期望值。

dp[i][j][k]表示放i个棋子,能盖住j行k列的概率。

由dp[i-1]也就是放i-1个棋子来推的话,如下图:


由这四种情况所推得的即为新的dp[i]。

代码如下:

#include <iostream>
#include <cstdio>
#include <cstring>
using namespace std;
double dp[3000][55][55];
int t, n, m;
void init() {
    memset(dp, 0, sizeof(dp));
    dp[0][0][0] = 1.0;
}
int main() {
    scanf("%d", &t);
    while(t--) {
        init();
        scanf("%d%d", &n, &m);
        if(n < m) swap(n, m);
        int max_day = n * m - m + 1;
        for(int i = 1; i <= max_day; i++) {
            for(int j = 1; j <= i && j <= n; j++) {
                for(int k = 1; k <= i && k <= m; k++) {
                    if(j == n && k == m) {
                        dp[i][j][k] = dp[i-1][j-1][k-1]*(double)(n-j+1)*(double)(m-k+1)/(double)(n*m-i+1)
                                      + dp[i-1][j][k-1]*(double)((m-k+1)*j)/(double)(n*m-i+1)
                                      + dp[i-1][j-1][k]*(double)((n-j+1)*k)/(double)(n*m-i+1);
                    } else {
                        dp[i][j][k] = dp[i-1][j-1][k-1]*(double)(n-j+1)*(double)(m-k+1)/(double)(n*m-i+1)
                                      + dp[i-1][j][k-1]*(double)((m-k+1)*j)/(double)(n*m-i+1)
                                      + dp[i-1][j-1][k]*(double)((n-j+1)*k)/(double)(n*m-i+1)
                                      + dp[i-1][j][k]*((double)(j*k)-(i-1))/(double)(n*m-i+1);
                    }
                }
            }
        }
        double ans = 0.0;
        for(int i = 1; i <= max_day; i++) {
            ans += double(i) * dp[i][n][m];
        }
        printf("%.10lf\n", ans);
    }
    return 0;
}


posted @ 2014-10-12 22:52  gaoxiang36999  阅读(144)  评论(0编辑  收藏  举报