[ACM] ZOJ 3329 One Person Game (概率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 Die1Die2 and Die3Die1 has K1 faces. Die2 has K2 faces. Die3 has K3 faces.
All the dice are fair dice, so the probability of rolling each value, 1 to K1K2K3 is exactly 1 / K1, 1 / K2 and 1 / K3. You have a counter,
and the game is played as follow:

  1. Set the counter to 0 at first.
  2. Roll the 3 dice simultaneously. If the up-facing number of Die1 is a, the up-facing number of Die2 is b and the up-facing number of Die3 is c, set the counter to 0. Otherwise,
    add the counter by the total value of the 3 up-facing numbers.
  3. If the counter‘s number is still not greater than n, go to step 2. Otherwise the game is ended.

Calculate the expectation of the number of times that you cast dice before the end of the game.

Input

There are multiple test cases. The first line of input is an integer T (0 < T <= 300) indicating the number of test cases. Then T test cases follow. Each test
case is a line contains 7 non-negative integers nK1K2K3abc (0 <= n <= 500, 1 < K1K2K3 <=
6, 1 <= a <= K1, 1 <= b <= K2, 1 <= c <= K3).

Output

For each test case, output the answer in a single line. A relative error of 1e-8 will be accepted.

Sample Input

2
0 2 2 2 1 1 1
0 6 6 6 1 1 1

Sample Output

1.142857142857143
1.004651162790698

Author: CAO, Peng

Source: The 7th Zhejiang Provincial Collegiate Programming Contest

解题思路:

有三枚骰子(下面用dice1,dice2, dice3表示,骰子太难拼),每一枚dice分别有k1,k2,k3个面,每个dice每个面上标的数字分别为 1到k1,   1到k2   ,  1到k3  ,每个dic都是均匀的。现在玩一个游戏,有一个计分器,初始为0,每次同时投三枚dice,如果dice1最上面显示的数字是a,dice2最上面显示的数字是b,dice3最上面显示的数字为c,那么计分器清0,否则计分器加上三枚dice最上面显示的数字之和,当计分器的分数>n时,游戏结束,求平均投的dice次数。

本题关系有环,不能直接使用递推..需要转化

下面思路转载:http://blog.csdn.net/morgan_xww/article/details/6775853  思路太棒了!括号里是我自己加的解释

设 E[i]表示现在分数为i,到结束游戏所要掷骰子的次数的期望值。

显然 E[>n] = 0; E[0]即为所求答案;

E[i] = ∑Pk*E[i+k] + P0*E[0] + 1;

Pk表示点数和为k的概率,P0表示分数清零的概率

(当前分数i掷骰子以后有两种情况,一是k是下一次掷骰子得到的分数,且不会清0,k需要累加,因为会出现很多种     分数,二是下一次掷骰子正好投出需要被清0的那种情况)

由上式发现每个 E[i]都包含 E[0],而 E[0]又是我们要求的,是个定值。

设 E[i] = a[i]*E[0] + b[i];

将其带入上面的式子:

E[i] = ( ∑Pk*a[i+k] + P0 )*E[0] + ∑Pk*b[i+k] + 1; (自己手动带入做一遍,看能不能得到这个式子)

显然,

a[i] = ∑Pk*a[i+k] + P0;

b[i] = ∑Pk*b[i+k] + 1;

当 i > n 时:

E[i] = a[i]*E[0] + b[i] = 0;

所以 a[i>n] = b[i>n] = 0;

可依次算出 a[n],b[n]; a[n-1],b[n-1] ... a[0],b[0];  (递推的关系就可以求出,从后往前)

则 E[0] = b[0]/(1 - a[0]); (最后答案)

代码:

#include <iostream>
#include <stdio.h>
#include <iomanip>
#include <string.h>
using namespace std;
const int maxn=520;
double A[maxn];
double B[maxn];
double p[maxn];//p[i]保存出现得分为i的概率
double p0;//三个dice任意转出三个数字和出现的概率
int n,k1,k2,k3,a,b,c;

void getP()
{
    for(int i=1;i<=k1;i++)
        for(int j=1;j<=k2;j++)
            for(int k=1;k<=k3;k++)
    {
        if(i!=a||j!=b||k!=c)
            p[i+j+k]+=p0;//因为出现i+j+k这个分数的概率为p0,这个分数可以出现过多次
    }
}

int main()
{
    int t;cin>>t;
    while(t--)
    {
        cin>>n>>k1>>k2>>k3>>a>>b>>c;
        memset(p,0,sizeof(p));
        memset(A,0,sizeof(A));
        memset(B,0,sizeof(B));
        p0=1.0/(k1*k2*k3);
        getP();
        for(int i=n;i>=0;i--)//原始分数
         {
             for(int j=3;j<=k1+k2+k3;j++)//三枚dice出现的分数
             {
                 A[i]+=p[j]*A[i+j];//递推公式
                 B[i]+=p[j]*B[i+j];
             }
             A[i]+=p0;
             B[i]+=1;
         }
         cout<<setiosflags(ios::fixed)<<setprecision(15)<<B[0]/(1-A[0])<<endl;
    }
    return 0;
}

[ACM] ZOJ 3329 One Person Game (概率DP,有环,巧妙转化)

时间: 2024-12-24 11:51:33

[ACM] ZOJ 3329 One Person Game (概率DP,有环,巧妙转化)的相关文章

zoj 3329 One Person Game 概率dp

先吐槽几句真心给数学跪了 题意: 有三个均匀的骰子,分别有k1,k2,k3个面,初始分数是0, 当掷三个骰子的点数分别为a,b,c的时候,分数清零,否则分数加上三个骰子的点数和, 当分数>n的时候结束.求需要掷骰子的次数的期望. 题解: 设 E[i]表示现在分数为i,到结束游戏所要掷骰子的次数的期望值. 显然 E[>n] = 0; E[0]即为所求答案; E[i] = ∑Pk*E[i+k] + P0*E[0] + 1; (Pk表示点数和为k的概率,P0表示分数清零的概率) 由上式发现每个 E[

ZOJ 3329 One Person Game 概率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 K3faces. All the d

ZOJ 3329 One Person Game 概率DP 期望 难度:2

http://acm.zju.edu.cn/onlinejudge/showProblem.do?problemId=3754 本题分数为0的概率不确定,所以不能从0这端出发. 设E[i]为到达成功所需的步数,明显i>n时E[i]=0,当0<i<=n时E[i]=sigma(E[i+k]*pk)+E[0]*p0,(k是可以投出的除了恰为a,b,c以外的骰子之和), 在这个公式里,E[i]和E[0]都是未知的,设E[0]=x,则 E[i]=sigma(E[i+k]*pk)+x*p0+1, 因

[ACM] poj 2096 Collecting Bugs (概率DP,期望)

Collecting Bugs Time Limit: 10000MS   Memory Limit: 64000K Total Submissions: 2026   Accepted: 971 Case Time Limit: 2000MS   Special Judge Description Ivan is fond of collecting. Unlike other people who collect post stamps, coins or other material st

ZOJ 3640 Help Me Escape 概率dp

有一个吸血鬼被困了,有n条路可以逃出去,每条路有一个难度c[],他初始的战斗力是f,对于第i条路,若f > c[i]他花t[i]天就能出去,否则,他就停留一天,同时战斗力增加c[i]然后再选一条路走出去,他走每条路的概率是相同的.问他逃出去的天数的期望. 设dp[i]表示在战斗力为i时逃出去的期望值,那么可推出状态方程 dp[i] = 1/n * t[j](c[j] > i),dp[i] = 1/n * (1+dp[ i+c[j] ] )( c[j] <= i). 需要注意的是终态的确定

zoj 3640 Help Me Escape (概率dp 递归求期望)

题目链接 Help Me Escape Time Limit: 2 Seconds      Memory Limit: 32768 KB Background     If thou doest well, shalt thou not be accepted? and if thou doest not well, sin lieth at the door. And unto thee shall be his desire, and thou shalt rule over him.  

ZOJ 3329-One Person Game(概率dp,迭代处理环)

题意: 三个色子有k1,2,k3个面每面标号(1-k1,1-k2,1-k3),一次抛三个色子,得正面向上的三个编号,若这三个标号和给定的三个编号a1,b1,c1对应则总和置零,否则总和加上三个色子标号和,直到总和不小于n时结束,求抛色子的期望次数. 分析: 该题状态好分析 dp[i]表示和为i时的期望次数,dp[0]是答案 dp[i]=sum(dp[i+tmp]*p[tmp])+dp[0]*p0+1(tmp是三个色子可得到的标号和); 第一次看到这样的方程不怎么解,看了题解才知道用迭代法,每个d

zoj 3812 We Need Medicine (dp 位优化 巧妙记录路径)

We Need Medicine Time Limit: 10 Seconds      Memory Limit: 65536 KB      Special Judge A terrible disease broke out! The disease was caused by a new type of virus, which will lead to lethal lymphoedema symptom. For convenience, it was namedLL virus.

zoj 3329 概率dp

看了这么多,也就是个递推 1 /* 2 ZOJ 3329 3 题意:有三个骰子,分别有k1,k2,k3个面. 4 每次掷骰子,如果三个面分别为a,b,c则分数置0,否则加上三个骰子的分数之和. 5 当分数大于n时结束.求游戏的期望步数.初始分数为0 6 7 设dp[i]表示达到i分时到达目标状态的期望,pk为投掷k分的概率,p0为回到0的概率 8 则dp[i]=∑(pk*dp[i+k])+dp[0]*p0+1; 9 都和dp[0]有关系,而且dp[0]就是我们所求,为常数 10 设dp[i]=A