ZOJ3329 概率DP变形

哇哦,感觉有点难哦,三个骰子,分别具有k1,k2,k3个面,抛骰子,若向上的一面分别对应为a,b,c,那么得分归0,否则得分加上三个骰子向上那一面数字之和,求得分超过n的时候抛骰子的次数的期望

一开始很容易想到常规的做法,以目标状态为边界,当前状态到目标状态所需要的期望为方程,dp[i]代表 当前到目标分数的期望,这是发现状态转移是这个样子的

dp[i] = dp[0] * p0 + sigma(pk * dp[i + k]) + 1;

p0,代表抛到分数归0 的概率,pk代表抛到分数为k的概率,这时候发现无法去做,因为我们所要求的答案就是dp[0],而每一步的状态转移里都包括了dp[0],同时前面是累积求和,这就相当于有个“环”一样,就像方程两边都有要求的未知数,但是无法移到同一边去,卡死了,首先觉得自己可能方程假设的不好,但是想了很久也没有其它的方程比这个合理了,后来看了这个博客:http://blog.csdn.net/xingyeyongheng/article/details/25639827

步骤讲解还是比较详细的,我是没有想到这个方面去,看了他的假设以后我就自己用草稿纸去往下推了,写了一大堆还是写出来了

首先假设dp[i] = A[i] * dp[0] + B[i];

这里发现dp[0] = A[0] * dp[0] + B[0];

目标就是要求出A[0],B[0],所以这个方程 要跟状态转移联系在一起的,

那么dp[i + k] = A[i + k] * dp[0] + B[i + k],然后把这个代入状态转移方程中去

dp[i] = dp[0] * p0 + sigma(pk*(A[i + k] * dp[0] + B[i + k])) + 1;化简一下

dp[i] = (sigma(pk * A[i + k]) + p0) * dp[0] + sigma(pk*B[i + k]) + 1;

那么A[i] = (sigma(pk * A[i + k]) + p0) ;

B[i] = sigma(pk*B[i + k]) + 1;

这里可以递推出A[0],B[0]

然后再回到假设方程去考虑

dp[0] = A[0] * dp[0] + B[0]

这里发现dp[0] 其实在这里不算是变量了,跟一个常数一样,所以上面才那样做出假设的,没有想到这点所以不知道如何处理,唉~

int t;

int k1,k2,k3,aa,bb,cc,n;

double pp[50 + 5];

double AA[500 + 55],BB[500 + 55];

void init() {
	memset(pp,0.00,sizeof(pp));
	memset(AA,0.00,sizeof(AA));
	memset(BB,0.00,sizeof(BB));
}

bool input() {
	while(cin>>n>>k1>>k2>>k3>>aa>>bb>>cc) {
		pp[0] = 1.0/k1 * 1.0/k2 * 1.0/k3;
		return false;
	}
	return true;
}

void cal() {
	for(int i=1;i<=k1;i++)
		for(int j=1;j<=k2;j++)
			for(int k=1;k<=k3;k++)
				if(i != aa || j != bb || k != cc)
					pp[i + j + k] += 1.0/k1 * 1.0/k2 * 1.0/k3;
	for(int i=n;i>=0;i--) {
		AA[i] = 0.00;
		BB[i] = 0.00;
		for(int k=1;k<= k1 + k2 + k3;k++) {
			AA[i] += pp[k] * AA[i + k];
			BB[i] += pp[k] * BB[i + k];
		}
		AA[i] += pp[0];
		BB[i] += 1.00;
	}
	double ans = BB[0]/(1 - AA[0]);
	printf("%.10lf\n",ans);
}

void output() {

}

int main() {
	cin>>t;
	while(t--) {
		init();
		if(input())return 0;
		cal();
		output();
	}
	return 0;
}
时间: 2024-10-13 10:49:47

ZOJ3329 概率DP变形的相关文章

ZOJ3329之经典概率DP

One Person Game Time Limit: 1 Second      Memory Limit: 32768 KB      Special Judge There is a very simple and interesting one-person game. You have 3 dice, namely Die1, Die2 and Die3. Die1 has K1 faces. Die2 has K2 faces. Die3 has K3 faces. All the

Codeforces 235B Let&#39;s Play Osu! (概率dp求期望+公式变形)

B. Let's Play Osu! time limit per test:2 seconds memory limit per test:256 megabytes You're playing a game called Osu! Here's a simplified version of it. There are n clicks in a game. For each click there are two outcomes: correct or bad. Let us deno

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 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 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个位置要到目的状

poj3071(概率DP)

题意:淘汰赛制,2^n(n<=7)个队员.给出相互PK的输赢概率矩阵.问谁最有可能赢到最后. 解法:ans[i][j]表示第i个队员第j轮胜出的概率.赢到最后需要进行n场比赛.算出每个人赢到最后的ans[i][n].写出序号的二进制发现一个规律,两个队员i.j如果碰到,那么一定是在第get(i,j)场比赛碰到的.get(i,j)计算的是i和j二进制不同的最高位,这个规律也比较明显. 代码: /****************************************************

【Foreign】开锁 [概率DP]

开锁 Time Limit: 10 Sec  Memory Limit: 256 MB Description Input Output Sample Input 4 5 1 2 5 4 3 1 5 2 2 5 4 3 1 5 3 2 5 4 3 1 5 4 2 5 4 3 1 Sample Output 0.000000000 0.600000000 0.900000000 1.000000000 HINT Main idea 一个宝箱内有一个可以开启别的宝箱的钥匙,可以选择k个宝箱,询问能开

POJ 2151 Check the difficulty of problems (概率DP)

题意:ACM比赛中,共M道题,T个队,pij表示第i队解出第j题的概率 ,求每队至少解出一题且冠军队至少解出N道题的概率. 析:概率DP,dp[i][j][k] 表示第 i 个队伍,前 j 个题,解出 k 个题的概率,sum[i][j] 表示第 i 个队伍,做出 1-j 个题的概率,ans1等于, T个队伍,至少解出一个题的概率,ans2 表示T个队伍,至少解出一个题,但不超过N-1个题的概率,最后用ans1-ans2即可. 代码如下: #pragma comment(linker, "/STA