首页 > 代码库 > zoj 3822 Domination(dp)
zoj 3822 Domination(dp)
题目链接:zoj 3822 Domination
题目大意:给定一个N?M的棋盘,每次任选一个位置放置一枚棋子,直到每行每列上都至少有一枚棋子,问放置棋子个数的期望。
解题思路:大白书上概率那一张有一道类似的题目,但是因为时间比较久了,还是稍微想了一下。
dp[i][j][k]表示i行j列上均有至少一枚棋子,并且消耗k步的概率(k≤i?j),因为放置在i+1~n上等价与放在i+1行上,同理列也是如此。所以有转移方程:
- dp[i][j][k+1]+=dp[i][j][k]?(n?k)(S?k)
- dp[i+1][j][k+1]+=dp[i][j][k]?(N?i)?j(S?k)
- dp[i][j+1][k+1]+=dp[i][j][k]?(M?j)?i(S?k)
- dp[i+1][j+1][k+1]+=dp[i][j][k]?(N?i)?(M?j)(S?k)
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
const int maxn = 55;
const int maxm = 2505;
int N, M;
double dp[maxn][maxn][maxm];
double solve () {
int S = N * M;
memset(dp, 0, sizeof(dp));
dp[1][1][1] = 1;
for (int i = 1; i <= N; i++) {
for (int j = 1; j <= M; j++) {
int n = i * j;
for (int k = max(i, j); k <= n; k++) {
dp[i][j][k+1] += dp[i][j][k] * (n - k) / (S - k);
dp[i+1][j][k+1] += dp[i][j][k] * (N - i) * j / (S - k);
dp[i][j+1][k+1] += dp[i][j][k] * (M - j) * i / (S - k);
dp[i+1][j+1][k+1] += dp[i][j][k] * (N - i) * (M - j) / (S - k);
}
}
}
/*
for (int i = 1; i <= N; i++) {
for (int j = 1; j <= M; j++) {
printf("%d %d:", i, j);
for (int k = max(i, j); k <= i * j; k++)
printf("%.3lf ", dp[i][j][k]);
printf("\n");
}
}
*/
double ans = 0;
for (int i = max(N, M); i <= S; i++)
ans += (dp[N][M][i] - dp[N][M][i-1]) * i;
return ans;
}
int main () {
int cas;
scanf("%d", &cas);
while (scanf("%d%d", &N, &M) == 2) {
printf("%.8lf\n", solve());
}
return 0;
}
zoj 3822 Domination(dp)
声明:以上内容来自用户投稿及互联网公开渠道收集整理发布,本网站不拥有所有权,未作人工编辑处理,也不承担相关法律责任,若内容有误或涉及侵权可进行投诉: 投诉/举报 工作人员会在5个工作日内联系你,一经查实,本站将立刻删除涉嫌侵权内容。