HDU3076 ssworld VS DDD概率DP

kao,WA了那么多次这题目数据是错的,两个人的血量弄错了,输入的 A的血量其实是B的,输入B的其实是A的,由于有平局现象的干扰,所以一开始先把平局包括进去 的 A赢的概率B赢的概率都算出来,然后减去以后就是平局的概率,再在已经除去平局的情况里 算一下A赢的概率,B赢得概率计算出来,这样就可以计算了,

假设方程dp[i][j]代表 A赢了j次B赢了i次的概率,然后状态转移就比较简单了 :

dp[i][j] += dp[i][j - 1] * a_win;

dp[i][j] += dp[i - 1][j] * b_win;

然后就是需要注意的是 B至多赢n-1次,而A必须恰好赢m次,

一开始没注意,当A已经赢了以后第二个状态转移已经不需要再加了,一开始没注意,第二个状态转移多加了一次

还有这破题目,数组要是开dp[2050][2050]就会MLE....必须差不多刚好2005 * 2005

double p1[7],p2[7];

int n,m;

double a_win,b_win;

double dp[2000 + 5][2000 + 5];

void init() {
	memset(dp,0.00,sizeof(dp));
}

bool input() {
	while(cin>>m>>n) {
		for(int i=1;i<=6;i++)cin>>p1[i];
		for(int i=1;i<=6;i++)cin>>p2[i];
		return false;
	}
	return true;
}

void cal() {
	a_win = 0.00;
	for(int i=2;i<=6;i++)
		for(int j=1;j<i;j++)
			a_win += p1[i] * p2[j];
	b_win = 0.00;
	for(int i=2;i<=6;i++)
		for(int j=1;j<i;j++)
			b_win += p2[i] * p1[j];
	double aa = a_win;
	double bb = b_win;
	double p = 1.00 - aa - bb;
	if(p + eps == 1.00 + eps) {a_win = 0.00,b_win = 0.00;}
	else {
		a_win = aa/(1 - p);
		b_win = bb/(1 - p);
	}
	dp[0][0] = 1.00;
	for(int j=0;j<=m;j++) {
		for(int i=0;i<n;i++) {
			if(i == 0 && j == 0)continue;
			if(j)dp[i][j] += dp[i][j - 1] * a_win;
			if(i && j != m)dp[i][j] += dp[i - 1][j] * b_win;
		}
	}
	double ans = 0.00;
	for(int i=0;i<n;i++)
		ans += dp[i][m];
	if(ans > 1 + eps)puts("1.000000");
	else printf("%.6lf\n",ans);
}

void output() {

}

int main() {
	while(true) {
		init();
		if(input())return 0;
		cal();
		output();
	}
	return 0;
}
时间: 2024-12-14 14:00:18

HDU3076 ssworld VS DDD概率DP的相关文章

hdu 3076 ssworld VS DDD (概率dp)

///题意: /// A,B掷骰子,对于每一次点数大者胜,平为和,A先胜了m次A赢,B先胜了n次B赢. ///p1表示a赢,p2表示b赢,p=1-p1-p2表示平局 ///a赢得概率 比一次p1 两次p0*p1 三次 p0^2*p1,即A赢的概率为p1+p*p1+p^2*p1+...p^n*p1,n->无穷 ///即a_win=p1/(1-p);b_win=p2/(1-p); ///dp[i][j]表示a赢了j次,b赢了i次的概率 ///dp[i][j]=dp[i-1][j]*b_win+dp[

HDU 3076 ssworld VS DDD 概率dp,无穷级数,oj错误题目 难度:2

http://acm.hdu.edu.cn/showproblem.php?pid=3076 不可思议的题目,总之血量越少胜率越高,所以读取时把两人的血量交换一下 明显每一轮的胜率和负率都是固定的,所以设psc为胜率,pls为负率,peq为平率, 则在每一局中的胜率负率平率可以确定, 而在有结果的一个阶段中的胜率和负率则各是一个无穷级数 psc(new)=1*psc+peq*psc+peq*peq*psc.......=lim(n->正无穷)(1-peq^n)*psc/(1-peq)=psc/(

hdu3076ssworld VS DDD 概率dp

//ssworld VS DDD 两个人有血量值 hp1 , hp2 //两人掷骰子得到每一点的概率已知 //ssword赢的概率 //dp[i][j]  表示有第一个人血量为i,第二个人的血量为j第一个人赢的概率 //第一个人赢,第二个人赢 , 平局的概率为p1 , p2 , p3 //那么有dp[i][j] = p2*dp[i-1][j] + p1*dp[i][j-1] + p3*dp[i][j] //整理可得dp[i][j] = p2/(1-p3)*dp[i-1][j] + p1/(1-p

hdu3076--ssworld VS DDD(概率dp第三弹,求概率)

ssworld VS DDD Time Limit: 4000/2000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others) Total Submission(s): 1487    Accepted Submission(s): 304 Problem Description One day, sssworld and DDD play games together, but there are some special

HDU3076 ssworld VS DDD

嘟嘟嘟 友情提示:数据把\(hp1\)和\(hp2\)弄反了! 进入正题. 这题还是比较好想,令\(dp[i][j]\)表示第一个人赢了\(i\)场,第二个人赢了\(j\)的概率,转移就是分别考虑这一场谁赢了. 所以我们要预处理两个人赢的概率.显然有\(winA = \sum _ {i = 1} ^ 6 \sum _ {j = 1} ^ {i - 1} p1[i] * p2[j]\),\(winB = \sum _ {i = 1} ^ 6 \sum _ {j = i + 1} ^ {n} p1[

HDU 3076:ssworld VS DDD(概率DP)

http://acm.split.hdu.edu.cn/showproblem.php?pid=3076 ssworld VS DDD Problem Description One day, sssworld and DDD play games together, but there are some special rules in this games.They both have their own HP. Each round they dice respectively and g

Codeforces 28C [概率DP]

/* 大连热身D题 题意: 有n个人,m个浴室每个浴室有ai个喷头,每个人等概率得选择一个浴室. 每个浴室的人都在喷头前边排队,而且每个浴室内保证大家都尽可能均匀得在喷头后边排队. 求所有浴室中最长队伍的期望. 思路: 概率dp dp[i][j][k]代表前i个浴室有j个人最长队伍是k的概率. 枚举第i个浴室的人数.然后转移的时候其实是一个二项分布. */ #include<bits/stdc++.h> using namespace std; int jilu[55]; double dp[

hdu 3853 概率DP 简单

http://acm.hdu.edu.cn/showproblem.php?pid=3853 题意:有R*C个格子,一个家伙要从(0,0)走到(R-1,C-1) 每次只有三次方向,分别是不动,向下,向右,告诉你这三个方向的概率,以及每走一步需要耗费两个能量,问你走到终点所需要耗费能量的数学期望: 回头再推次,思想跟以前的做过的类似 注意点:分母为0的处理 #include <cstdio> #include <cstring> #include <algorithm>

hdu4089(公式推导)概率dp

题意:有n人都是仙剑5的fans,现在要在官网上激活游戏,n个人排成一个队列(其中主角Tomato最初排名为m), 对于队列中的第一个人,在激活的时候有以下五种情况: 1.激活失败:留在队列中继续等待下一次激活(概率p1) 2.失去连接:激活失败,并且出队列然后排到队列的尾部(概率p2) 3.激活成功:出队列(概率p3) 4.服务器瘫:服务器停止服务了,所有人都无法激活了(概率p4) 求服务器瘫痪并且此时Tomato的排名<=k的概率. 解法:ans[i][j]表示i个人出于第j个位置要到目的状