这道题目,我看了好多篇博客,都没有看到过很好的解释, 不过在这位大佬这里看到了,很棒的解释。
用的是概率dp做的,dp[i][j]表示的是有i只老虎和j只鹿的情况下,人的最大存活概率,因为dp[0][j]都是0可以从下往上递推;
状态转移方程是:
我们只要解一下这个方程,把dp[i][j],移到一边就可以了。
#include <iostream>
#include <stdio.h>
#include <algorithm>
#include <cstring>
using namespace std;
#define Max_N 1010
int T, n, m;
double dp[Max_N][Max_N];
int main()
{
scanf("%d", &T);
int num = 0;
while (T--) {
scanf("%d%d", &n, &m);
num++;
if(n%2) {
printf("Case %d: 0\n", num);
continue;
}
memset(dp, 0, sizeof(dp));
for (int i = 0; i <= m; i++)
dp[0][i] = 1;
for (int i = 1; i <= n; i++) {
for (int j = 0; j <= m; j++) {
double r1, r2;
r1 = 0;
r2 = 0;
if (i >= 2)
r1 += i * (i - 1) * 1.0 / ((i + j + 1) * (i + j)) * dp[i-2][j];
if (j >= 1)
r1 += j * i * 2.0 / ((i + j + 1) * (i + j)) * dp[i][j-1];
double p = 0;
if (j >= 2) {
p = (j * (j - 1) * 1.0) / ((i + j + 1) * (i + j));
}
if (j >= 1) {
r2 = r1;
r2 += j * 2.0 / ((i + j + 1) * (i + j)) * dp[i][j - 1];
r2 /= (1 - p);
}
r1 /= (1 - p - j * 2.0 / ((i + j + 1) * (i + j)));
dp[i][j] = max(r1, r2);
}
}
printf("Case %d: %.12f\n", num, dp[n][m]);
}
return 0;
}