链接:http://codeforces.com/contest/540/problem/D
大体题意:
岛上有三个物种,石头r个,剪刀s个,布p个,冤家路窄,每天都会相遇两个物种,其中石头能杀掉剪刀,布能杀掉石头,剪刀能杀掉布,问最后只剩下石头,剪刀,布 的三个概率是多少?
思路:
很明显是概率DP,比赛果然没有什么思路 = =:
令dp[i][j][k]表示剩下i个石头,剩下j 个剪刀的,剩下k 个布的概率!
转移:
三个情况嘛, 那一天要么石头被吃,要么剪刀被吃,要么布被吃:
石头被吃: dp[i-1][j][k] = dp[i][j][k] * i*k/sum; 就是所有的布遇到所有的石头是事件总和,也就是i*k,而sum 是所所有的情况 sum = i*j + i*k + j*k;
其余的类似:
剪刀被吃:dp[i][j-1][k] += dp[i][j][k] * i*j*1.0/sum;
布被吃:dp[i][j][k-1] += dp[i][j][k] * j*k*1.0/sum;
最后统计剩下那个物种 累计求和即可!
详细见代码:
#include<bits/stdc++.h>
using namespace std;
const int maxn = 100 + 10;
double dp[maxn][maxn][maxn];
int main(){
int r,s,p;
scanf("%d %d %d",&r,&s,&p);
dp[r][s][p] = 1.0;
for (int i = r; i >= 0; --i){
for (int j = s; j >= 0; --j){
for (int k = p; k >= 0; --k){
if (i == 0 && j == 0 && k == 0)goto TT;
double sum = i*j + i*k + k*j;
if (i && k)dp[i-1][j][k] += dp[i][j][k] * i*k*1.0/sum;
if (j && i)dp[i][j-1][k] += dp[i][j][k] * i*j*1.0/sum;
if (k && j)dp[i][j][k-1] += dp[i][j][k] * j*k*1.0/sum;
}
}
}
TT:
double ans1 = 0.0,ans2 = 0.0,ans3 = 0.0;
for (int i = 1; i <= 100; ++i){
ans1 += dp[i][0][0];
ans2 += dp[0][i][0];
ans3 += dp[0][0][i];
}
printf("%.14lf %.14lf %.14lf\n",ans1,ans2,ans3);
return 0;
}