ZOJ 3329 One Person Game:期望dp【关于一个点成环——分离系数】

题目链接:http://acm.zju.edu.cn/onlinejudge/showProblem.do?problemCode=3329

题意:

  给你面数分别为k1,k2,k3的三个骰子。

  给定a,b,c三个整数。

  三个骰子每扔一次,若骰子朝上的点数分别为a,b,c,则分数清零,否则当前分数+=骰子点数之和。

  当分数 > n时游戏结束。

  问你扔骰子次数的期望。

题意:

  表示状态:

    dp[i] = rest steps

    (当前分数为i时,剩余步数的期望)

  找出答案:

    ans = dp[0]

    刚开始分数为0。

  如何转移:

    由于此题中可以由高分数转移到低分数,所以转移存在环。

    一般有环dp用高斯消元做。

    但是,此题的所有环都跟dp[0]有关,也就是说所有的转移都能写成形如 dp[i] = a[i]*dp[0] + b[i] 的形式(分离系数)。

    那么求出a[0]和b[0]就可以行了,答案为dp[0] = b[0] / (1-a[0])。

    (1)dp[i] = sigma(dp[i+k]*p[k]) + dp[0]*p[0] + 1 (原转移方程,p[i]为扔出点数为i的概率,p[0]为扔出(a,b,c)的概率)

    (2)dp[i] = a[i]*dp[0] + b[i] (假设的)

    将(2)代入(1):

      dp[i] = sigma( (a[i+k]*dp[0] + b[i+k]) * p[k] ) + dp[0]*p[0] + 1

      dp[i] = sigma( a[i+k]*dp[0]*p[k] + b[i+k]*p[k] ) + dp[0]*p[0] + 1

      dp[i] = ( sigma(a[i+k]*p[k]) + p[0] )*dp[0] + sigma(b[i+k]*p[k]) + 1

    系数对应相等:

      a[i] = sigma(a[i+k]*p[k]) + p[0]

      b[i] = sigma(b[i+k]*p[k]) + 1

    递推求出a[i] & b[i]即可,求的时候要保证i <= n(有意义)。

    dp[0] = b[0] / (1-a[0])。

AC Code:

  1 // state expression:
  2 // dp[i] = rest steps
  3 // i: present score
  4 //
  5 // find the answer:
  6 // ans = dp[0]
  7 //
  8 // transferring:
  9 // 1) dp[i] = sigma(dp[i+k]*p[k]) + dp[0]*p[0] + 1
 10 // 2) dp[i] = a[i]*dp[0] + b[i]
 11 // ***solve:
 12 // dp[i] = sigma( (a[i+k]*dp[0] + b[i+k]) * p[k] ) + dp[0]*p[0] + 1
 13 // dp[i] = sigma( a[i+k]*dp[0]*p[k] + b[i+k]*p[k] ) + dp[0]*p[0] + 1
 14 // dp[i] = ( sigma(a[i+k]*p[k]) + p[0] )*dp[0] + sigma(b[i+k]*p[k]) + 1
 15 // ***result:
 16 // a[i] = sigma(a[i+k]*p[k]) + p[0]
 17 // b[i] = sigma(b[i+k]*p[k]) + 1
 18 // ***run:
 19 // cal a[i] & b[i]
 20 // dp[0] = b[0] / (1-a[0])
 21 //
 22 // boundary:
 23 // set a,b = 0
 24 #include <iostream>
 25 #include <stdio.h>
 26 #include <string.h>
 27 #define MAX_N 505
 28 #define MAX_K 40
 29
 30 using namespace std;
 31
 32 int n,t;
 33 int k1,k2,k3;
 34 int e1,e2,e3;
 35 double p[MAX_K];
 36 double a[MAX_N];
 37 double b[MAX_N];
 38 double dp[MAX_N];
 39
 40 void read()
 41 {
 42     cin>>n>>k1>>k2>>k3>>e1>>e2>>e3;
 43 }
 44
 45 void cal_pro()
 46 {
 47     memset(p,0,sizeof(p));
 48     p[0]=1.0/(k1*k2*k3);
 49     for(int i=1;i<=k1;i++)
 50     {
 51         for(int j=1;j<=k2;j++)
 52         {
 53             for(int k=1;k<=k3;k++)
 54             {
 55                 if(i!=e1 || j!=e2 || k!=e3)
 56                 {
 57                     p[i+j+k]+=p[0];
 58                 }
 59             }
 60         }
 61     }
 62 }
 63
 64 void cal_const()
 65 {
 66     memset(a,0,sizeof(a));
 67     memset(b,0,sizeof(b));
 68     for(int i=n;i>=0;i--)
 69     {
 70         for(int k=1;k<=k1+k2+k3;k++)
 71         {
 72             if(i+k>n) break;
 73             a[i]+=a[i+k]*p[k];
 74             b[i]+=b[i+k]*p[k];
 75         }
 76         a[i]+=p[0];
 77         b[i]+=1.0;
 78     }
 79 }
 80
 81 void solve()
 82 {
 83     cal_pro();
 84     cal_const();
 85     dp[0]=b[0]/(1.0-a[0]);
 86 }
 87
 88 void print()
 89 {
 90     printf("%.15f\n",dp[0]);
 91 }
 92
 93 int main()
 94 {
 95     cin>>t;
 96     while(t--)
 97     {
 98         read();
 99         solve();
100         print();
101     }
102 }
时间: 2024-10-27 11:45:25

ZOJ 3329 One Person Game:期望dp【关于一个点成环——分离系数】的相关文章

[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 Die1, Die2 and Die3. Die1 has K1 faces. Die2 has K2 faces. Die3 has K3 faces. All the

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, 因

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

先吐槽几句真心给数学跪了 题意: 有三个均匀的骰子,分别有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 概率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

【bzoj4872】[Shoi2017]分手是祝愿 数论+期望dp

题目描述 Zeit und Raum trennen dich und mich. 时空将你我分开. B 君在玩一个游戏,这个游戏由 n 个灯和 n 个开关组成,给定这 n 个灯的初始状态,下标为从 1 到 n 的正整数.每个灯有两个状态亮和灭,我们用 1 来表示这个灯是亮的,用 0 表示这个灯是灭的,游戏的目标是使所有灯都灭掉.但是当操作第 i 个开关时,所有编号为 i 的约数(包括 1 和 i)的灯的状态都会被改变,即从亮变成灭,或者是从灭变成亮.B 君发现这个游戏很难,于是想到了这样的一个

HDOJ 1145 So you want to be a 2n-aire? 期望DP

期望DP So you want to be a 2n-aire? Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others) Total Submission(s): 267    Accepted Submission(s): 197 Problem Description The player starts with a prize of $1, and is asked a seq

HDU 4336 Card Collector (期望DP+状态压缩 或者 状态压缩+容斥)

题意:有N(1<=N<=20)张卡片,每包中含有这些卡片的概率,每包至多一张卡片,可能没有卡片.求需要买多少包才能拿到所以的N张卡片,求次数的期望. 析:期望DP,是很容易看出来的,然后由于得到每张卡片的状态不知道,所以用状态压缩,dp[i] 表示这个状态时,要全部收齐卡片的期望. 由于有可能是什么也没有,所以我们要特殊判断一下.然后就和剩下的就简单了. 另一个方法就是状态压缩+容斥,同样每个状态表示收集的状态,由于每张卡都是独立,所以,每个卡片的期望就是1.0/p,然后要做的就是要去重,既然

Topcoder SRM656div1 250 ( 期望DP )

Problem Statement    Charlie has N pancakes. He wants to serve some of them for breakfast. We will number the pancakes 0 through N-1. For each i, pancake i has width i+1 and deliciousness d[i].Charlie chooses the pancakes he is going to serve using t