Poj 2300
http://poj.org/problem?id=2300
题目大意
Stan和Ollie每年夏天都会来到Ex,Stan喜欢玩Crown & Anchor.
Crown & Anchor是一个猜图案的游戏:Crown, Anchor, Club, Diamond, Heart, Spade一共六种图案
轮子旋转并最终停止在一个拥有3个以上组合图案的位置。
如果斯坦赌注中有最终位置中指出的三个符号之一,他会收到他的本金和n倍押注的奖金,其中n是他的下注符号出现的次数。
以前每年,斯坦都在输钱,奥利嘲笑他。
今年,斯坦与奥利(Ollie)进行了一个下注:他要打败Ollie赚钱。
Ollie不蠢,意识到斯坦有可能会幸运地赢前几轮,所以他坚持认为,斯坦至少领先k轮才算斯坦赢。
Ex最多m轮的游戏 之后将会关闭,为了赢得Stan,Ollie必须在最多m轮内获得利润。
Stan藏了一手,他最近学会了蒙特卡洛的投注策略。这个想法是他先下最低的赌注。
如果他赢了,他会收取他的奖金,并再次给予最低的赌注。
如果他输了,他会下双倍的赌注,如果他赢下一轮,他将赢得足够的收益,以弥补以前的损失并赚取利润。
这一直下去,直到他赢了。 无论何时他赢了,他都会赢利,并以最低的赌注重新开始。
Stan认为这是一个伟大的战略,但是首先建立思想,并实施了一个限制 - 斯坦斯可以在任何轮下的最大赌注是多少。
(假定Stan无限多钱)
Stan修改了他的策略,以便如果他的投注数超过最大限额,他将以最低的下注开始,希望能够收回他的损失。
如果按照这个策略,Stan需要在K轮内保持领先,或者在第m+1轮之前,他就能获得胜利。 斯坦将赢得下注的几率是多少?
输入:
第一行输入包含n个测试用例数。
0≤k≤m≤30 ; 2≤l≤1000。
最小赌注为1。
输出:
一个0到1的概率
想法
不难猜想 每个图案的个数是一样的(不然就不会随机对一个图案下注了),这样就得出选定一个图案后:
转到有1个该图案的转板概率为2/14
转到有2个该图案的转板概率为1/14
转到有3个该图案的转板概率为1/14
转化为编程的思想
2/14:一倍收益 1/14:两倍收益 2/14:三倍收益 10/14:亏掉本钱
根据逻辑 代码如下:
//poj2300
//San
#include<iostream>
#include <iomanip>
using namespace std;
void count(int benifit, int bet, int round, double rate);
int k, m, l;
double frate;
double fail = 10.0 / 14;
double win1 = 2.0 / 14;
double win2 = 1.0 / 14;
double win3 = 1.0 / 14;
int winround = 0; //赢得轮数,当连续k轮收益大于0时直接胜利
int main()
{
int n;
frate = 0.0; //用于计算每次胜利的概率和
cin >> n;
for (int i = 0; i < n; i++)
{
frate = 0;
winround = 0;
cin >> k >> m >> l;
count(0, 1, 0, 1); //初始是 收益0、赌注1、轮数0、初始概率1
cout << fixed << setprecision(4) << frate;//输出控制4位
}
return 0;
}
void count(int benifit, int bet, int round, double rate)
{
if (benifit > 0)
winround++;
else
winround = 0;
if ((round >= m || winround >= k))
{
if (benifit>0)
frate += rate;
}
else if (benifit>0)
{
count(benifit + bet, 1, round + 1, rate*win1);
count(benifit + 2 * bet, 1, round + 1, rate*win2);
count(benifit + 3 * bet, 1, round + 1, rate*win3);
if (bet * 2>l)
{
if (benifit - bet > 0)
{
count(benifit - bet, 1, round + 1, rate*fail);
}
else
{
count(benifit - bet, 1, round + 1, rate*fail);
}
}
else
{
if (benifit - bet > 0)
{
count(benifit - bet, 2 * bet, round + 1, rate*fail);
}
else
{
count(benifit - bet, 2 * bet, round + 1, rate*fail);
}
}
}
else
{
count(benifit + bet, 1, round + 1, rate*win1);
count(benifit + 2 * bet, 1, round + 1, rate*win2);
count(benifit + 3 * bet, 1, round + 1, rate*win3);
if (bet * 2>l)
{
if (benifit - bet > 0)
{
count(benifit - bet, 1, round + 1, rate*fail);
}
else
{
count(benifit - bet, 1, round + 1, rate*fail);
}
}
else
{
if (benifit - bet > 0)
{
count(benifit - bet, 2 * bet, round + 1, rate*fail);
}
else
{
count(benifit - bet, 2 * bet, round + 1, rate*fail);
}
}
}
}
总结
概率事件多次重复,是递归的象征,我在多次提交的过程中出现了超时的现象,应该可以在逻辑上进一步优化。
应该有统计的方法的。。后来想不出了 先放着吧。