题意:有三个骰子,分别有k1,k2,k3个面。
每次掷骰子,如果三个面分别为a,b,c则分数置0,否则加上三个骰子的分数之和。
当分数大于n时结束。求游戏的期望步数。初始分数为0
设dp[i]表示达到i分时到达目标状态(即i = n)的期望,pk为投掷k分的概率,
p0为回到0的概率则dp[i] = ∑(pk * dp[i + k]) + dp[0] * p0 + 1 ;
都和dp[0]有关系,而且dp[0]就是我们所求,为常数设
dp[i] = A[i] * dp[0] + B[i];
即为dp[i + k] = A[i + k] * dp[0] + B[i + k];
将其代入原式:dp[i] = ∑(pk * A[i + k] * dp[0] + pk * B[i + k]) + dp[0] * p0 + 1
= (∑(pk * A[i + k]) + p0) * dp[0] + ∑(pk * B[i + k]) + 1;
所以可得:A[i] = ∑(pk * A[i + k]) + p0
B[i] = ∑(pk * B[i + k]) + 1
先递推求得A[0]和B[0]。那么 dp[0] = B[0] / (1 - A[0]);
Source Code:
//#pragma comment(linker, "/STACK:16777216") //for c++ Compiler #include <stdio.h> #include <iostream> #include <fstream> #include <cstring> #include <cmath> #include <stack> #include <string> #include <map> #include <set> #include <list> #include <queue> #include <vector> #include <algorithm> #define Max(a,b) (((a) > (b)) ? (a) : (b)) #define Min(a,b) (((a) < (b)) ? (a) : (b)) #define Abs(x) (((x) > 0) ? (x) : (-(x))) #define MOD 1000000007 #define pi acos(-1.0) using namespace std; typedef long long ll ; typedef unsigned long long ull ; typedef unsigned int uint ; typedef unsigned char uchar ; template<class T> inline void checkmin(T &a,T b){if(a>b) a=b;} template<class T> inline void checkmax(T &a,T b){if(a<b) a=b;} const double eps = 1e-7 ; const int N = 210 ; const int M = 1100011*2 ; const ll P = 10000000097ll ; const int MAXN = 10900000 ; int n, k1, k2, k3, ka, kb, kc; double a[600], b[600], p[100]; int main(){ std::ios::sync_with_stdio(false); int i, j, t, k, u, v, numCase = 0; cin >> t; while(t--){ cin >> n >> k1 >> k2 >> k3 >> ka >> kb >> kc; memset(p, 0, sizeof(p)); for(i = 1; i <= k1; ++i){ for(j = 1; j <= k2; ++j){ for(k = 1; k <= k3; ++k){ if(i == ka && j == kb && k == kc){ p[0] += 1.0 / (k1 * k2 * k3); continue; } p[i + j + k] += 1.0 / (k1 * k2 * k3); } } } memset(a, 0, sizeof(a)); memset(b, 0, sizeof(b)); for(i = n; i >= 0; --i){ a[i] = p[0]; b[i] = 1.0; for(k = 1; k <= k1 + k2 + k3; ++k){ a[i] += p[k] * a[i + k]; b[i] += p[k] * b[i + k]; } } printf("%.16f ",b[0] / (1.0 - a[0])); } return 0; }