LightOJ_1265:Island_of_Survival(概率DP/想法题)

12 篇文章 0 订阅
4 篇文章 0 订阅

题目大意是岛上有一个人,t只老虎和d只鹿,每天都会有两个生物随机碰面,有以下几种情况①老虎与人碰面,人被吃掉②老虎与鹿碰面,鹿被吃掉③老虎与老虎,两只老虎同归于尽④鹿与鹿碰面,什么都不会发生⑤鹿与人碰面,人可以选择杀死鹿或不杀鹿(取决于你),问最后人存货下来的最大概率.

经典的概率DP问题,设a[i][j]为岛上剩i只老虎和j只鹿的情况,计算每个a[i][j]时先算出第①②③种情况,随后再按照概率算出后两种情况的做法会比较好处理,因为会涉及某一状态有某种概率会指向自己的情况.

#include<iostream>
#include<stdio.h>
#include<string.h>
#include<stdlib.h>
using namespace std;
#define ll long long
const int N=1001;
double a[N][N];
double maxx(double x,double y){if(x>y)y=x;return y;}
int main(void)
{
	int i,j,k,cas;double p,t;cas=0;
	for(i=0;i<N;i++)a[0][i]=1;
	for(i=1;i<N;i++)
	for(j=0;j<N;j++)
	{
		if(i==1&&j==0){a[i][j]=0;continue;}
		a[i][j]=0;
		p=(1+i+j)*(i+j)/2;
		if(i&&j)a[i][j]+=i*j/p*a[i][j-1];
		if(i>=2)a[i][j]+=i*(i-1)/2/p*a[i-2][j];
		if(j>=2){t=a[i][j]/(1-j*(j-1)/2/p-j/p)*(1-j/p);a[i][j]=t+j/p*maxx(t/(1-j/p),a[i][j-1]);}
		else if(j)a[i][j]=a[i][j]+j/p*maxx(a[i][j]/(1-j/p),a[i][j-1]);
	}
	scanf("%d",&k);
	while(k--)
	{
		scanf("%d%d",&i,&j);
		printf("Case %d: %.8f\n",++cas,a[i][j]);
	}
	return 0;
}

而在ac了这道题之后又跑去找别人不一样的做法,然后在看了某种做法后顿时觉得自己傻x了,大致思路如下.

因为在整个决策过程中,鹿的存在与否并不会对最后的结果产生影响,why?Becase决定人最后存活与否的最关键的因素在于老虎们是否全部死亡,而鹿并不会让人或者老虎数量发生变化,且让老虎死亡的唯一可能就是在某天有两只老虎碰面了,而且老虎如果死亡则一定是成双成对地死(<_<),所以我们计算人最后存活的概率则等价于计算老虎在碰见人之前就全部gg的概率.

所以结论就很明显了,当老虎是奇数时,人一定会死,当老虎数量为0时,则人一定存活,而当老虎的数量为非零偶数时,设有t只老虎,无视掉鹿参与碰面的情况,则在前t/2个有老虎参与碰面的日子里(因为有t只老虎,所以第t/2+1天时只会剩下一只虎或一个人)选取t个生物参与碰面,若不区分老虎,则总情况数为C(t+1,t)=C(t+1,1)=t+1,而人能存活的情况就是选取的t个生物为全部的t只老虎,情况数为C(t,t)=1,则人最后能够存活的概率便是(能够存活的情况)/(总情况)=1/(t+1),这道题到这儿才算是完美解出.

下附程序,明显要比上面那一坨要短了好多(然后大概可以无视掉lz为了少写几个if而拼凑的嵌套三目运算符(<v<)

#include<iostream>
#include<stdio.h>
#include<string.h>
#include<stdlib.h>
using namespace std;
int main(void)
{
	int i,j,k,cas;cas=0;
	scanf("%d",&k);
	while(k--)
	{
		scanf("%d%d",&i,&j);
		printf("Case %d: %.8f\n",++cas,(i)?((i&1)?(0):(1.0/(i+1))):(1));
	}
	return 0;
}


  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值