您的位置:首页 > 其它

ZOJ 3822 Domination

2015-07-12 23:15 405 查看
ZOJ Problem Set - 3822

Domination

Time Limit: 8 Seconds
Memory Limit: 131072 KB Special Judge

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


Author: JIANG, Kai

Source: The 2014 ACM-ICPC Asia Mudanjiang Regional Contest

这是一道概率DP题,dp[i][j][k]表示K颗棋子们占领有I行有J列时的概率。它由之前的四种状态得来,比如最后一颗棋子能给整体增加一行或者一列或者一行一列或者什么都不加。最后算期望的时候,由于K颗棋子的时候包括了前面K-1颗棋子I行J列的情况,所以算期望的时候需要减掉。

<以下解释来自网上>



最后算答案的时候注意到,题目问的是到第k个刚好放完n行m列,也就是最后一个棋子一定是有作用的,

所以用dp[i][j][k]-dp[i][j][k-1]得到是第k个棋子恰好使得每行每列都占领的概率。

#include<iostream>
#include<cstdio>
#include<cstring>
using namespace std;
	double dp[55][55][5000];
int main()
{
	long long T;
	cin >> T;
	while(T--)
	{

		long long n,m;
		cin >> n >> m;
	
		memset(dp,0,sizeof(dp));
		dp[0][0][0]=1;
		for(int i=1;i<=n;i++)
			for(int j=1;j<=m;j++)
			{
				for(int k=max(i,j);k<=n*m;k++)
				{
					
					double p1 = dp[i-1][j][k-1]*(n-(i-1))*j;
					double p2 = dp[i][j-1][k-1]*(m-(j-1))*i;
					double p3 = dp[i-1][j-1][k-1]*(n-(i-1))*(m-(j-1));
					double p4 = dp[i][j][k-1]*(i*j-(k-1));
					dp[i][j][k] = (p1+p2+p3+p4)/(n*m-(k-1));
				}
			}
			double ans = 0;
			for(int i=max(n,m);i<=n*m;i++)
			{
				ans += (dp
[m][i]-dp
[m][i-1])*i;
			}
			printf("%.12f\n",ans);

	}
	return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: