ZOJ 3329 One Person Game
题意:给定n,k1,k2,k3,a,b,c七个数。有三个骰子,第一个骰子有k1个面,第二个有k2个面,第三个有k3个面,摇骰子得到的点数即为摇动后向上的面的点数,每一个面向上的概率相同。一个人的分数记为count,初始时count=0,然后同时摇三个骰子记为一次摇动,每次摇动之后,三个骰子分别得到x1,x2,x3点,若x1=a且x2=b且x3=c,则count=0,否则,count += x1+x2+x3。若count > n,则游戏结束,否则继续游戏。问摇动次数的期望。
解法:在做了POJ 2096 Collecting Bugs之后,已经大概懂得怎样用DP处理期望问题了。DP求概率要正推,求期望要倒推。
但是,当我写出状态转移的方程的时候,又发现了一个新问题,就是这道题是带环的期望问题。一般而言,带环的问题都要用高斯消元来做,但这道题其实不用那么麻烦。
设E[i]表示count = i的情况下,平均还需要摇多少次骰子,才能结束游戏。p[i]表示摇骰子后count需要加i分的概率,p[0]表示摇骰子后count置0的概率。
状态转移方程为:E[i] = E[i+1]*p(1) + E[i+2]*p(2) + E[i+3]*p[3].....+E[i+k]*p[k] + E[0]*p[0] + 1。
可以发现,每个状态转移方程的未知量都是E[0],所以这道题就有了下面解法:
设E[i] = a[i]*E[0] + b[i],则由上面的状态转移方程又有E[i] = (segma(a[i+x]*p[x]) + p[0]) * E[0] + segma(b[[i+x]*p[x]) + 1。
所以有a[i] = segma(a[i+x]*p[x]) + p[0],b[i] = segma(b[i+x]*p[x]) + 1。而答案E[0] = b[0] / (1-a[0])。这样就可以用DP解决问题了。
tag:math, 概率DP, 代数变形
1 /* 2 * Author: Plumrain 3 * Created Time: 2013-10-30 09:57 4 * File Name: math-ZOJ-3329.cpp 5 */ 6 #include<iostream> 7 #include<cstdio> 8 #include<cstring> 9 10 using namespace std; 11 12 #define CLR(x) memset(x, 0.0, sizeof(x)) 13 14 int n, tot; 15 double p[20], a[1000], b[1000]; 16 17 void init() 18 { 19 int k[3], tmp, sum = 0; 20 scanf ("%d", &n); 21 for (int i = 0; i < 3; ++ i) 22 scanf ("%d", &k[i]); 23 for (int i = 0; i < 3; ++ i){ 24 scanf ("%d", &tmp); 25 sum += tmp; 26 } 27 28 int num[20]; CLR (num); 29 for (int i = 1; i <= k[0]; ++ i) 30 for (int j = 1; j <= k[1]; ++ j) 31 for (int l = 1; l <= k[2]; ++ l) 32 ++ num[i+j+l]; 33 -- num[sum]; 34 35 int mul = k[0] * k[1] * k[2]; 36 tot = k[0] + k[1] + k[2]; 37 num[0] = 1; 38 for (int i = 0; i <= tot; ++ i) 39 p[i] = (double)num[i] / mul; 40 } 41 42 double DP() 43 { 44 CLR (a); CLR (b); 45 for (int i = n; i >= 0; -- i){ 46 a[i] = p[0]; 47 b[i] = 1.0; 48 for (int j = 1; j <= tot; ++ j){ 49 a[i] += a[i+j] * p[j]; 50 b[i] += b[i+j] * p[j]; 51 } 52 } 53 54 return b[0] / (1 - a[0]); 55 } 56 57 int main() 58 { 59 int T; 60 scanf ("%d", &T); 61 while (T--){ 62 init(); 63 printf ("%.10f\n", DP()); 64 } 65 return 0; 66 }
现在的你,在干什么呢?
你是不是还记得,你说你想成为岩哥那样的人。