LightOJ 1265 Island of Survival 概率DP
Island of Survival LightOJ - 1265
一个岛上有 个老虎和 鹿,还有一个人,每次从中选出来两种动物(包括人),进行操作:
(1)人 和 老虎:老虎吃人
(2)老虎 和 鹿:老虎吃鹿
(3)鹿 和 鹿:啥都不发生
(4)人 和 鹿:人可以选择吃或不吃鹿
(5)老虎 和 老虎:两败俱伤,都死掉
当老虎都死掉的时候人获得胜利,问人的获胜概率是多大(遇见鹿时通过选择来最大化获胜概率)?
首先,老虎必须是偶数只,才有可能都死掉,所以 为奇数时获胜概率为 ;其次,每次人遇见鹿时选择不杀,这样有更大的概率给老虎选到鹿。
然后用 表示还有 只老虎, 只鹿时人的获胜概率,,则:
代码如下:
#include<iostream>
#include<cstdio>
//#define WINE
#define MAXN 1005
using namespace std;
int T,iCase,t,d,sum;
double dp[MAXN][MAXN],res;
int main(){
#ifdef WINE
freopen("data.in","r",stdin);
#endif
scanf("%d",&T);
while(T--){
scanf("%d%d",&t,&d);
if(t%2!=0){
printf("Case %d: 0\n",++iCase);
continue;
}
for(int i=0;i<=t;i+=2)
for(int j=0;j<=d;j++){
if(i==0){
dp[i][j]=1;
continue;
}
sum=(i+j+1)*(i+j)-j-j*j;
dp[i][j]=i*(i-1)*1.0/sum*dp[i-2][j];
if(j!=0)dp[i][j]+=2.0*i*j/sum*dp[i][j-1];
}
printf("Case %d: %.10lf\n",++iCase,dp[t][d]);
}
return 0-1;
}
还有一种解法是,输赢只和老虎数量有关,设 为有 只老虎时,人获胜的概率,则:
代码如下:
#include<iostream>
#include<cstdio>
//#define WINE
#define MAXN 1005
using namespace std;
int T,iCase,t,d;
double dp[MAXN];
int main(){
#ifdef WINE
freopen("data.in","r",stdin);
#endif
scanf("%d",&T);
while(T--){
scanf("%d%d",&t,&d);
if(t%2!=0){
printf("Case %d: 0\n",++iCase);
continue;
}
dp[0]=1;
for(int i=2;i<=t;i+=2)
dp[i]=1.0*(i-1)/(i+1)*dp[i-2];
printf("Case %d: %.8lf\n",++iCase,dp[t]);
}
return 0;
}
(没写时间是因为用时 0ms…)