【翻译】GCJ 2008 APAC local onsites C Millionaire 题解

原文:https://code.google.com/codejam/contest/32005/dashboard#s=a&a=2


挑战说的题解太模糊了。。我的智商理解不能。所以去翻译原文。。。没有逐字逐句翻译,因为那样翻译成中文有点奇怪……


The problem explicitly states that the contestant has an infinite number of degrees of freedom. She can bet ANY fraction of her current amount. This makes it impossible to brute force over all of the possible bets. The trick is to discretize the problem.


题目说明你每一次可以赌的钱,都有无数种可能。(你有10块,你可以赌1块,1.1块,1.11块,1.111块…… 所以有无限可能)。这样,题目成功的让我们不能暴力搜索了……所以这题的核心是要离散化这个问题。


Following one of the principles in problem solving, we look at the easier cases. The problem is easy if there is one round. We suggest you do it for the case when there are two rounds. It is not hard, but it reveals the interesting nature of the problem. The figure below illustrates the situation in the second-to-last round, the last round and after the last round. 


根据上述规则,首先我们考虑一个简单的情况…… 假设我们只能赌博一轮,和赌2轮。然后我们就可以找到一个规律~ 下面的图说明了这个情况


【翻译】GCJ 2008 APAC local onsites C Millionaire 题解_第1张图片


The colors represent different probability zones. All sums in a probability zone share the same probability of winning. The important sums are marked and labeled.


不同的颜色代表不同的概率区间~ 颜色越深概率月底。不同的金额,在同一个区间是同样的概率。图上已经做了标记。



If we know the probability of winning for all sums in the next round Pnext(sum), then the probability of winning in this round is:


如果我们知道下一轮拥有sum这个金额获胜的概率Pnext(sum),我们就可以求出这一轮获胜的概率。


p * Pnext(sum + stake) + (1 - p) Pnext(sum - stake),

where stake is the amount we are betting.

公式里的stake是我们要这一轮要赌的钱


这个公式显然是对的。 但是时间复杂度过高不可接受。


Now, given the existence and location of the important sums in the next round, we can find the locations of the important sums in this round. The figure below illustrates how we find these sums. The midpoints between the important sums of the next round become important in this round. I.e in the case of the green point in figure 2, we can move up by lowering the stake, and we can move down by increasing the stake, without changing the end probability. The probability of the blue, green and red points is the same. This also illustrates that the probability in a 'probability zone' which is limited by two important sums is equal to the probability at the lower important sum. 


现在我们知道下一轮的几个分界线(图上的2500000,5000000这类分界线),我们可以很快求出这一轮的分界线。下图说明我们如何求出这些分界线。


【翻译】GCJ 2008 APAC local onsites C Millionaire 题解_第2张图片


下一轮两个边界的中间的点,就是这一轮的新的边界。

显然在一个区间里随便移动,获胜的概率都是相同的。


Conclusion: The important sums of round i are the union of the important sums of round (i+1)  and their midpoints. We need to consider $0 an important sum in the last round because we can't bet more than we have.


我们得到一个结论,就是第 i 轮的所有区间的边界就是第 i+1 轮的边界,和他们边界的重点。 我们只需要考虑0元到当前拥有的钱来下注就可以了。(尼玛这句话怎么翻译的?)


Now, we only need to compute probabilities at the important sums, bootstrapping at 1.0 for $1000000, and 0.0 for $0 in the last round. Then, going backwards, we fill the probabilities at the important sums in the previous rounds.


我们只需要求出概率即可。一步一步的从1元到1000000元。最后再倒着回填数据即可。


By the limits of the input, we may try all the stakes that lead to important points in the next round. It is an interesting question whether there are mathematical properties that could reduce the complexity of this computation, but that is beyond the scope of this analysis.


由于输入的限制,我们可能做过多的计算,我们再想办法解决一下就好了。



———————— 其实我就是想知道最后如何解决这个问题!!!然而居然没分析!!


我翻译的太烂了,以后不写翻译了,唉……英语水平不行啊


然后我的程序比挑战的程序慢好多……挑战的jub太厉害了!

#include <iostream>
#include <cstdio>
#include <cstring>
#include <cstdlib>
#include <algorithm>
#include <vector>
#include <cmath>
#include <vector>
#include <bitset>
#include <ctime>
using namespace std;

#define LL long long
void nextInt(int &x)
{
	scanf("%d", &x);
}
void nextInt(int &x, int &y)
{
	scanf("%d%d", &x, &y);
}

int lun, qi;
double p;
const int mudi = 1000000;
double a[17][(1<<16) + 10];

void init()
{
	cin >> lun;
	cin >> p;
	cin >> qi;
	int tot = 1 << lun;
	memset(a, 0, sizeof(a));
	a[lun][tot] = 1; 

//	cout << tot <<" " << lun << endl;


	double sb=clock();
	for (int r = lun - 1; r >= 0; -- r)
	{
		for (int i = 1; i <= tot; ++ i)// 范围(0,i]的资金可以用于赌博
		{
			for (int j = 0; j <=i && i + j <= tot; ++ j)//穷举读博的资金,
			{
				a[r][i] = max((1-p) * a[r + 1][i - j] + p * a[r + 1][i + j], a[r][i]);
			}
		//	cout<<r<<" "<<i<<" "<<a[r][i]<<endl;
		}
	}
	double k = (double)mudi / tot;
	for (int i = 1; i <= tot + 1; ++ i)
		if (qi >= k * i)
		{
			continue;
		}else
		{
//			cout << a[0][i - 1] << endl;
			printf("%.6f\n", a[0][i - 1]);
			break;
		}
	//cout << (clock()-sb)/1000 << endl;
}

/*

1
13 0.662817 357055

*/

int main()
{
	//freopen("a.txt","r",stdin);
	//freopen("C-large.out","w",stdout);
	LL sb;
	scanf("%lld", &sb);
	for (int i = 1; i <= sb; ++ i)
	{
		printf("Case #%d: ", i);
		init();
	}
	return 0;
}

/*
3
5 0.547173 843749
1 0.5 500000
3 0.75 600000

*/


你可能感兴趣的:(【翻译】GCJ 2008 APAC local onsites C Millionaire 题解)