D - Domination ZOJ - 3822[概率dp]

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/m0_38081836/article/details/83420036

题意:问期望多少天能把一个n*m的棋盘放成每一行每一列都至少有一个棋子的样子,一天只能放一个。


题解:动态规划,可以考虑 d p [ i ] [ j ] [ k ] dp[i][j][k] 为i天放了i行和j列的概率,然后可以通过当前状态可以转移到下一天的概率。
如使 i + 1 i+1 天 :

  1. 占i行和j列
  2. 占i+1行和j+1列
  3. 占i行j+1列
  4. 占i+1行j列

具体转移见代码。


收获:概率不是平均值,这也是为什么暴力的结果是2.8。


a c   c o d e : ac\ code:

/**hqx is the best**/
/*****数组大小*****/
/**hqx is the best**/
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
#define debug cerr << "*" << endl;
#define rep(i, a, b) for(int i = a; i <= b; i++)
#define pre(i, a, b) for(int i = a; i >= b; i--)
#define met(a, b) memset(a, b, sizeof(a))
const int maxn = 41 + 10;
const int inf = 0x3f3f3f3f;
int T, n, m;

double dp[maxn * maxn][maxn][maxn];

int main() {
    scanf("%d", &T);
    while(T--) {
        scanf("%d%d", &n, &m);
        met(dp, 0.0);
        dp[1][1][1] = 1.0;
        for(int i = 1; i <= n * m; i++) {
            for(int j = 1; j <= n; j++) {
                for(int k = 1; k <= m; k++) {
                    dp[i + 1][j][k] += dp[i][j][k] * 1.0 * (j * k - i) / (double)(n * m - i);
                    dp[i + 1][j + 1][k] += dp[i][j][k] * 1.0 * ((n - j) * k) / (double)(n * m - i);
                    dp[i + 1][j][k + 1] += dp[i][j][k] * 1.0 * ((m - k) * j) / (double)(n * m - i);
                    dp[i + 1][j + 1][k + 1] += dp[i][j][k] * 1.0 * ((m - k) * (n - j)) / (double)(n * m - i);
                }
            }
        }
        double ans = 0.0;
        for(int i = 1; i <= n * m; i++) {
            ans += 1.0 * (dp[i][n][m] - dp[i - 1][n][m]) * i;
        }
        printf("%.10f\n", ans);
    }
    return 0;
}

猜你喜欢

转载自blog.csdn.net/m0_38081836/article/details/83420036
今日推荐