CSU 1725 加尔鲁什·地狱咆哮对阵虚灵大盗拉法姆

                              E - 加尔鲁什·地狱咆哮对阵虚灵大盗拉法姆

                            Time Limit:1000MS    Memory Limit:131072KB    64bit IO Format:%lld & %llu

Description

加尔鲁什·地狱咆哮看虚灵大盗拉法姆不顺眼已经很久了,终于一天,加尔鲁什·地狱咆哮带着自己的手下恐怖的奴隶主堵住了虚灵大盗拉法姆,虚灵大盗拉法姆拉法姆见势不妙,掏出神器死亡丧钟准备还击。场面十分壮观,如图:

已知恐怖丧钟每一发击中敌方单位都将令对方的生命值减一,且击中每个敌方单位的概率是相等的。而恐怖的奴隶主有3点生命值,当其在场上受到非致命伤害且场上恐怖的奴隶主总数小于7时会召唤一个新的3点生命值的恐怖的奴隶主,受到致命伤害(受到攻击后生命为0)时则会直接死去。如场上有1个生命值为3的“恐怖的奴隶主”,当恐怖丧钟打中他时,他的生命值变为2,且召唤一个新的奴隶主。而当恐怖丧钟击中加尔鲁什时,恐怖的奴隶主只会强力围观却什么都不会做。

现知,恐怖丧钟共计会发射X次,加尔鲁什有Y点体力值,而他手下共有Z名生命值为三的奴隶主。问在死亡丧钟使用完毕后,有多大的概率杀死加尔鲁什?(答案保留小数点后6位)

Input

多组数据,第一行有一个整数T,表示有T组数据。(T<=100)
以下T行,每行有三个整数X,Y和Z。(1<=X,Y<=20,0<=Z<=7)

Output

一个小数(保留小数点后六位)。

Sample Input

4
1 1 1
2 1 1
2 1 2
2 2 2

Sample Output

0.500000
0.666667
0.500000
0.111111

概率dp。dp[x][y][a][b][c]:表示恐怖丧钟还能发射x次,加尔布鲁什还有y点体力,有a只生命值为三的奴隶主,b只生命值为2的
奴隶主,c只生命值为1的奴隶主的情况下,能杀死加尔布鲁什的概率。
记忆化搜索即可。


#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<string>
using namespace std;
const int N = 25;
double dp[N][N][8][8][8];
int t, x, y, z;
void init()
{
	for (int i = 0; i < N; i++)
		for (int j = 0; j < N; j++)
			for (int k = 0; k < 8; k++)
				for (int kk = 0; kk < 8; kk++)
					for (int kkk = 0; kkk < 8; kkk++)
						dp[i][j][k][kk][kkk] = -1;
}
double dfs(int x, int y, int a, int b, int c)
{
	if (dp[x][y][a][b][c] != -1)
		return dp[x][y][a][b][c];
	if (y == 0)
		return dp[x][y][a][b][c] = 1.0;
	if (x < y||!x) dp[x][y][a][b][c] = 0;
	else
	{
		dp[x][y][a][b][c] = double(1) / (a + b + c + 1)*dfs(x - 1, y - 1, a, b, c);
		if (a + b + c < 7)
		{
			if (a > 0) dp[x][y][a][b][c] += double(a) / (a + b + c + 1)* dfs(x - 1, y, a, b + 1, c);
			if (b > 0) dp[x][y][a][b][c] += double(b) / (a + b + c + 1)* dfs(x - 1, y, a + 1, b - 1, c + 1);
			if (c > 0) dp[x][y][a][b][c] += double(c) / (a + b + c + 1)* dfs(x - 1, y, a, b, c - 1);
		}
		else
		{
			if (a > 0) dp[x][y][a][b][c] += double(a) / (a + b + c + 1)* dfs(x - 1, y, a - 1, b + 1, c);
			if (b > 0) dp[x][y][a][b][c] += double(b) / (a + b + c + 1)* dfs(x - 1, y, a, b - 1, c + 1);
			if (c > 0) dp[x][y][a][b][c] += double(c) / (a + b + c + 1)* dfs(x - 1, y, a, b, c - 1);
		}
	}
	return dp[x][y][a][b][c];
}
int main()
{
	freopen("in.txt", "r", stdin);
	scanf("%d", &t);
	while (t--)
	{
		init();
		scanf("%d%d%d", &x, &y, &z);
		printf("%.6lf\n", dfs(x, y, z, 0, 0));
	}
	return 0;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值