ZOJ 3329 One Person Game [概率DP]

Description

There is a very simple and interesting one-person game. You have 3 dice, namely Die1Die2 and Die3Die1 has K1 faces. Die2 has K2faces. 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.

題意:

給出3個骰子,每個骰子的面數已知,並且對於每個骰子來說每一面出現的概率是相等的,當三個骰子分別爲A,B,C時,計數器清0,否則加上三個骰子的點數和,問計數器大於N的期望投擲數。

解法:

假設DP[i]表示當前點數爲i,達到大於N的狀態的期望,那麼DP[ >N ] =0

DP[I]=p*DP[0]+Σ (pk*dp[i+k]) +1

最後我們要解的便是dp[0],但是每一個dp[I]裏面都含有了一個DP[0],我們需要把其前面的係數提取出來

設DP[I] = A[I] * DP[0] +B[I] 

那麼DP[0]=A[0]*DP[0]+B[0]

推出DP[0]=B[0]/(1-A[0])

A[I]=Σ(A[I+k]*pk)+p

B[I]=Σ(B[I+K]*pk)+1.0

代碼:

#include<stdio.h>
#include<string.h>
#include<algorithm>
#include<math.h>
#include<iostream>
#include<stdlib.h>
#include<set>
#include<map>
#include<queue>
#include<vector>
#include<bitset>
#pragma comment(linker, "/STACK:1024000000,1024000000")
template <class T>
bool scanff(T &ret){ //Faster Input
    char c; int sgn; T bit=0.1;
    if(c=getchar(),c==EOF) return 0;
    while(c!='-'&&c!='.'&&(c<'0'||c>'9')) c=getchar();
    sgn=(c=='-')?-1:1;
    ret=(c=='-')?0:(c-'0');
    while(c=getchar(),c>='0'&&c<='9') ret=ret*10+(c-'0');
    if(c==' '||c=='\n'){ ret*=sgn; return 1; }
    while(c=getchar(),c>='0'&&c<='9') ret+=(c-'0')*bit,bit/=10;
    ret*=sgn;
    return 1;
}
#define inf 1073741823
#define llinf 4611686018427387903LL
#define PI acos(-1.0)
#define lth (th<<1)
#define rth (th<<1|1)
#define rep(i,a,b) for(int i=int(a);i<=int(b);i++)
#define drep(i,a,b) for(int i=int(a);i>=int(b);i--)
#define gson(i,root) for(int i=ptx[root];~i;i=ed[i].next)
#define tdata int testnum;scanff(testnum);for(int cas=1;cas<=testnum;cas++)
#define mem(x,val) memset(x,val,sizeof(x))
#define mkp(a,b) make_pair(a,b)
#define findx(x) lower_bound(b+1,b+1+bn,x)-b
#define pb(x) push_back(x)
using namespace std;
typedef long long ll;
typedef pair<int,int> pii;

double pa[1111];
double pb[1111];
int n,k1,k2,k3,a,b,c;
double p[111],pe;
int main(){
    tdata{
        scanff(n);scanff(k1);scanff(k2);scanff(k3);
        scanff(a);scanff(b);scanff(c);
        int tot=k1+k2+k3;
        mem(p,0);
        p[0]=1.0/double(k1*k2*k3);
        rep(i,1,k1)
        rep(j,1,k2)
        rep(k,1,k3){
            if(i==a&&j==b&&k==c)continue;
            int sum=i+j+k;
            p[sum]+=1.0/double(k1*k2*k3);
        }
        mem(pa,0);
        mem(pb,0);
        drep(i,n,0){
            rep(j,1,tot){
                pa[i]+=pa[i+j]*p[j];
                pb[i]+=pb[i+j]*p[j];
            }
            pa[i]+=p[0];
            pb[i]+=1.0;
        }
        double ans=pb[0]/(1.0-pa[0]);
        printf("%.15f\n",ans);
    }
    return 0;
}


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章