zoj 3822 dp

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 Nrows 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
本题为2014年牡丹江赛区区域赛的一道dp题,本题的整体难度还是比较简单的,状态很容易就能想出来,用dp[i][j][k]表示在放第k个棋子的时候已经有i行j列被放过的情况,然后就是推公式了,分为四种情况:
第一种,放第k个棋子的时候没有占新的一行也没有占新的一列。
第二种,放第k个棋子的时候占了新的一行但是没有占新的一列。
第三种,放第k个棋子的时候占了新的一列但是没有占新的一行。
第四种,放第k个棋子的时候占了新的一行同时也占了新的一列。
详见代码:
#include
#include
#include
#include
using namespace std;
double dp[60][60][3600] , ans;
int main()
{
	int T , n , m;
	scanf("%d", &T);
	while (T--)
	{
		scanf("%d%d", &n, &m);
		memset(dp, 0.0, sizeof(dp));
		ans = 0.0;
		dp[0][0][0] = 1;
		for (int k = 0; k < n * m; ++k)
		{
			for (int i = 0; i <= n; ++i)
			{
				for (int j = 0; j <= m; ++j)
				{
					if (i == n && j == m)
					{
						break;
					}
					int sum = n * m - k;
					int p1 = i * j - k;
					int p2 = (n - i) * j;
					int p3 = i * (m - j);
					int p4 = (n - i) * (m - j);
					dp[i][j][k + 1] += dp[i][j][k] * (p1 * 1.0 / sum); ///表示第一种情况,这个时候总的可以放棋子的位置是sum个,符合这种情况的位置的个数为p1个,以下三种情况同上
					dp[i + 1][j][k + 1] += dp[i][j][k] * (p2 * 1.0 / sum);
					dp[i][j + 1][k + 1] += dp[i][j][k] * (p3 * 1.0 / sum);
					dp[i + 1][j + 1][k + 1] += dp[i][j][k] * (p4 * 1.0 / sum);
				}
			}
			ans += k * dp[n][m][k];
		}
		ans += (n * m) * dp[n][m][n * m];
		printf("%.10f\n", ans);
	}
	return 0;
}

你可能感兴趣的:(动态规划,DP,zoj)