ACM学习历程——ZOJ 3822 Domination (2014牡丹江区域赛 D题)(概率,数学递推)

Description

Edward is the headmaster of Marjar University. He is enthusiastic about chess and often plays chess with his friends. What's more, he bought a large decorative chessboard with N rows and M columns.

Every day after work, Edward will place a chess piece on a random empty cell. A few days later, he found the chessboard was dominated by the chess pieces. That means there is at least one chess piece in every row. Also, there is at least one chess piece in every column.

"That's interesting!" Edward said. He wants to know the expectation number of days to make an empty chessboard of N × M dominated. Please write a program to help him.

Input

There are multiple test cases. The first line of input contains an integer T indicating the number of test cases. For each test case:

There are only two integers N and M (1 <= N, M <= 50).

Output

For each test case, output the expectation number of days.

Any solution with a relative or absolute error of at most 10-8 will be accepted.

Sample Input

2
1 3
2 2

Sample Output

3.000000000000
2.666666666667 这个题目可以设一个概率函数p(i, j, k)表示用k个石子覆盖i行j列的概率,可以先算出所有的p值,然后就是概率乘天数加和求出期望。
然而对于概率的递推,可以考虑以下四种情况:
1、由p(i-1, j-1, k-1)在没有被覆盖的行切其列没有被覆盖的格子里放上一个石子;
2、由p(i-1, j, k-1)在没有被覆盖的一行放上一个石子;
3、由p(i, j-1, k-1)在没有被覆盖的一列放上一个石子;
4、由p(i-1, j-1, k-1)在被覆盖过行且列的格子里放上一个石子;
不过需要注意,在计算p(n, m, ?)时不需要加上第四项。
然而对于每一种都有其自己的概率系数,这个系数在代码里会有体现。(满足条件的格子数目/剩余总格子数目)ps:关键在于找满足条件的格子数目。 代码:
#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <cmath>
#include <set>
#include <map>
#include <vector>
#include <string>
#include <queue>
#define inf 0x3fffffff
#define esp 1e-10
#define N 55 using namespace std; double p[N][N][N*N]; double qt (int n, int m)
{
memset (p, , sizeof(p));
int len = n*m;
p[][][] = ;
for (int i = ; i <= n; ++i)
{
for (int j = ; j <= m; ++j)
{
for (int k = ; k <= len; ++k)
{
p[i][j][k] = p[i-][j-][k-]/(n*m-k+)*(n-i+)*(m-j+);
p[i][j][k] += p[i-][j][k-]/(n*m-k+)*(n-i+)*j;
p[i][j][k] += p[i][j-][k-]/(n*m-k+)*i*(m-j+);
if (i != n || j != m)
p[i][j][k] += p[i][j][k-]/(n*m-k+)*(i*j-k+);
}
}
}
double ans = ;
for (int k = ; k <= len; ++k)
ans += p[n][m][k]*k;
return ans;
} int main()
{
//freopen ("test.txt", "r", stdin);
int T;
scanf ("%d", &T);
for (int times = ; times < T; ++times)
{
int n, m;
scanf ("%d%d", &n, &m);
printf ("%.10lf\n", qt (n, m));
}
return ;
}

上一篇:python中的日志操作和发送邮件


下一篇:Coin Toss(uva 10328,动态规划递推,限制条件,至少转至多,高精度)