HDU - 6558 The Moon(概率dp)

题目

The Moon card shows a large, full moon in the night’s sky, positioned between two large towers. The Moon is a symbol of intuition, dreams, and the unconscious. The light of the moon is dim, compared to the sun, and only vaguely illuminates the path to higher consciousness which winds between the two towers.

Random Six is a FPS game made by VBI(Various Bug Institution). There is a gift named “Beta Pack”. Mr. K wants to get a beta pack. Here is the rule.
Step 0. Let initial chance rate q = 2%.
Step 1. Player plays a round of the game with winning rate p.
Step 2. If the player wins, then will go to Step 3 else go to Step 4.
Step 3. Player gets a beta pack with probability q. If he doesn’t get it, let q = min(100%, q + 2%) and he will go to Step 1.
Step 4. Let q = min(100%, q + 1.5%) and goto Step 1.
Mr. K has winning rate p% , he wants to know what’s the expected number of rounds before he needs to play.
Input
The first line contains testcase number T (T ≤ 100). For each testcase the first line contains an integer p (1 ≤ p ≤ 100).
Output
For each testcase print Case i : and then print the answer in one line, with absolute or relative error not exceeding 106.
Sample Input
2
50
100
Sample Output
Case 1: 12.9933758002
Case 2: 8.5431270393

题意
玩一个游戏,每个回合流程如下:
0.初始完成概率q%为2%
1.进行比赛,胜率为p%,如果胜利进入第二步,否则进入第三步
2.进行完成判定,如果完成则游戏结束,否则将完成概率+2%然后进入第一步
3.完成概率增加1.5%,进入第三步
问要结束游戏需要多少个回合

思路
一开始觉得是简单数学题,就写了一个假算法,能过样例2但是怎么都过不了样例1,后来找了找题解,发现基本都是概率dp做的,我是第一次做到这样的题(刷题太少orz,以后一定改过自新)
用dp[i]表示在胜率为i时完成的回合数期望,因为胜率存在0.5,因此把下标都乘二。胜率最高为100%,因此初始状态为dp[200],这时我们只需要赢就能结束,因此dp[200] = 1 / p。
转移方程为:
dp[i] = 1 + p * (1 - q) * dp[min(200, i + 4)] + (1 - p) * dp[min(200, i + 3)]
其中1为当前回合, p * (1 - q) * dp[min(200, i + 4)]为胜利但完成判定失败的情况,(1 - p) * dp[min(200, i + 3)]为失败的情况

代码

#include<bits/stdc++.h>
using namespace std;

#define ll long long
#define IO ios::sync_with_stdio(false);cin.tie(0);cout.tie(0)

int t;
double dp[205];

int main(void) {
    
    
	IO;
	int c = 1;
	cin >> t;
	while(t--) {
    
    
		double p;
		cin >> p;
		memset(dp, 0, sizeof(dp));
		dp[200] = 100 / p;
		for(int i = 199; i >= 4; i--)
			dp[i] = 1 + (p / 100) * (1 - i / 200.0) * dp[min(200, i + 4)] + (1 - p / 100) * dp[min(200, i + 3)];
		
		printf("Case %d: %.10lf\n", c++, dp[4]);
	}
}

猜你喜欢

转载自blog.csdn.net/qq_45682135/article/details/109323114