您的位置:首页 > 其它

ZOJ 3329 One Person Game [概率DP]

2015-11-29 18:06 609 查看
Description

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 K2faces. Die3 has K3 faces.
All the dice are fair dice, so the probability of rolling each value, 1 to K1, K2, K3 is exactly 1 / K1, 1 / K2 and 1 /K3. You have a counter,
and the game is played as follow:

Set the counter to 0 at first.
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.
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 n, K1, K2, K3, a, b, c (0
<= n <= 500, 1 < K1, K2, K3 <= 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;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: