這道題目,我看了好多篇博客,都沒有看到過很好的解釋, 不過在這位大佬這裏看到了,很棒的解釋。
用的是概率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;
}