筛子游戏

筛子游戏题解

题目大意:

吉吉国王正在玩一款手游,这个手游的规则非常简单。一开始你会得到三个筛子,三个筛子分别有\(k1, k2, k3\)面,也就是说分别可以扔出[1, k1], [1, k2], [1, k3]之间数。一开始的分数为\(0\),每次扔筛子都会扔出\(x, y, z\)三个数,但是这个游戏的特别之处在于每次开局都会给定三个数\(a, b, c\),如果满足\(x = a, y = b, z = c\),那么你的分数就会清零,否则你的分数就会加上\(x + y + z\)。现在吉吉国王想知道需要扔多少次才能使得他的分数大于\(n\)

题目分析:

先令\(k = k1 + k2 + k3\),首先我们是可以预处理出来[3, K]每一步可能增加数值的概率,对于0情况特殊判断,我们假定dp[i]代表的含义为当前数值为i时,他还需要扔的期望数,使得他的分数大于n,从而我们可以推出一个状态转移方程$dp[i] = $$\sum$dp[i + k] * p[i + k] + \(dp[0] * p[0]\) + \(1\),而我们知道dp[0]是我们要求的答案,通过这个式子我们是无法直接得到答案的,所以我们令\(dp[i] = A[i] * dp[0] + B[i]\),将该式,带入进求和符号中的式子中,将有关\(dp[0]\)的部分,放在一起,可化简为,$dp[i] = $ (\(\sum\)A[i + k] * p[k] + \(p[0]\)) * \(dp[0]\) + \(\sum\)B[i + k] * p[k] + 1, 可以发现这和我们开始假定的式子很像,所以我们可以认为$A[i] = $$\sum$A[i + k] * p[k] + \(p[0]\), $B[i] = $ \(\sum\) B[i + k] * p[k] + 1. 而我们的答案$dp[0] = $ $B[0] / $$(1 - A[0])$.

代码:

#include<bits/stdc++.h>
using namespace std;
double dp[30004];
double A[30004];
double B[30004];
int main(){
	int n, k1, k2, k3, a, b, c;
	cin >> n >> k1 >> k2 >> k3 >> a >> b >> c;
	for (int i = 1; i <= k1; ++i){
		for (int j = 1; j <= k2; ++j){
			for (int k = 1; k <= k3; ++k3){
				if (i == a && j == b && k == c){
					dp[0]++;
				}else{
					dp[i + j + k] ++;
				}
			}
		}
	}
	int K = i + j + k;
	for (int i = 0; i <= K; ++i){
		dp[i] = dp[i] / (K * 1.0);
	}
	for (int i = n; i >= 0; --i){
		A[i] += dp[0];
		B[i] += 1;
		for (int j = 3; j <= K; ++j){
			if (i + j > n) continue;
			A[i] += A[i + j] * dp[j];
			B[i] += B[i + j] * dp[j];
		}
	}
	double ans = 0;
	ans = b[0] / (1 - A[0]);
	printf("%.6lf",ans);
}
posted @ 2022-12-30 19:34  zkhcwy  阅读(72)  评论(0编辑  收藏  举报