HDU 1493 QQpet exploratory park(dp)

Problem Description

Today, more and more people begin to raise a QQpet. You can get a lot of pleasure from it, although it does not have a real life and it calls for huge patience to take care of it. There is a place called QQpet exploratory park in the world. Every week, you can get a chance to have a joy there for free. The whole park contains 61 grids in a line, numbered from 0 to 60. Ten of them are important grids which will touch off ( 引发 ) an incident when the pet stands on. They are 5, 12, 22, 29, 33, 38, 42, 46, 50 and 55. Your pet is standing on the gird of number 0 in the beginning. You can toss the die ( 掷骰子 ) 10 times. Each time, the pet goes ahead n steps which n is the number from the die ( n ∈{ 1, 2, …, 6 } ). If your RP is great enough( calls RPG for short ), you will get many surprises in the important grids, such as some yuanbao( the money in QQpet world ), an improvement of your pet’s ability, and the most attractive gift-package. Now, your task is to calculate the probability(概率) of touching each important grid.

Input

The first line of the input contains an integer t– determining the number of datasets. Then t lines follows. Each line contains 6 numbers pi, i ∈{ 1, 2, …, 6 }, indicating the probability of getting 1 to 6 after you toss the die every time . p1+ p2+ … + p6 = 1.

Output

For each test case, output the probability of touching each important grid. accurate up to 1 decimal places. There is a blank line between test cases. See the Sample Output to get the exactly output format.

Sample Input

2
0.000 1.000 0.000 0.000 0.000 0.000
0.500 0.000 0.000 0.000 0.000 0.500

Sample Output

5: 0.0%
12: 100.0%
22: 0.0%
29: 0.0%
33: 0.0%
38: 0.0%
42: 0.0%
46: 0.0%
50: 0.0%
55: 0.0%

5: 3.1%
12: 30.5%
22: 27.3%
29: 24.6%
33: 21.9%
38: 10.9%
42: 0.8%
46: 0.0%
50: 4.4%
55: 1.0%

思路

每一步都是由上一步走1-6步得到的,那么到每一格的概率,就是上一步的概率乘上相应步数的概率的累加和。递归实现,注意算出一个格子后储存,之后可能会用。

代码

#include<iostream>
#include<iomanip>
#include<cstring>
using namespace std;

const int key[]={
    
    0,5,12,22,29,33,38,42,46,50,55};
double f[65][11];									// f[i][j]第j步走到第i格 
bool vis[65][11];									//标记是否判断 
double ans[11];										//答案 

double work(int aim,int cnt)						//aim 目标格  cnt 当前步数 
{
    
    
	if(vis[aim][cnt])								//判断过返回 
		return f[aim][cnt];
	for(int i=1;i<=6&&aim-i>0&&cnt>1;i++)			//上一个格子累加 
	{
    
    
		f[aim-i][cnt-1]=work(aim-i,cnt-1);			//记录 
		f[aim][cnt]+=f[aim-i][cnt-1]*f[i][1];
		vis[aim-i][cnt-1]=1;						//标记 
	}
	vis[aim][cnt]=1;								//标记 
	return f[aim][cnt];
}

int main()
{
    
    
	int t;
	cin>>t;
	while(t--)
	{
    
    
		memset(f,0,sizeof(f));						//数据重置 
		memset(vis,0,sizeof(vis));
		memset(ans,0,sizeof(ans));
		for(int i=1;i<=6;i++)
			cin>>f[i][1];							//第一步 
		for(int i=1;i<=10;i++)
		{
    
    
			for(int j=1;j<=10;j++)
			{
    
    	
				f[key[i]][j]=work(key[i],j);		//不同步数到第i格概率累加 
				ans[i]+=f[key[i]][j];
			}
			ans[i]*=100;							//格式 
			cout<<key[i]<<": "<<setprecision(1)<<fixed<<ans[i]<<"%"<<endl;
		}
		if(t)
			cout<<endl;								//最后一个测试不换行 
	}
}

猜你喜欢

转载自blog.csdn.net/m0_54621932/article/details/113998402