基本上,问题模拟了以下内容:
有一个有50个绿球和50个红球的骨灰盒。
我被允许从瓮中挑球,没有替换,遵守以下规则:对于每一个挑选的红球,我输了一美元,因为每一个选中的绿球,我都会获得一美元。
我可以随时停止挑选。最糟糕的情况是我选择全部100和净0。
问题是提出一个最佳停止策略,并创建一个程序来计算策略的预期价值。
我的策略是继续挑球,而选择另一球的预期值是正值。
也就是说,停止规则是DYNAMIC。
在Latex中,这是图像中的递归公式:
http://i.stack.imgur.com/fnzYk.jpg
#include <stdio.h>
#include <math.h>
#include <stdlib.h>
double ExpectedValue(double, double);
double max(double, double);
main() {
double g = 50;
double r = 50;
double EV = ExpectedValue(g, r);
printf ("%f\n\n", EV);
system("PAUSE");
}
double ExpectedValue(double g, double r){
double p = (g / (g + r));
double q = 1 - p;
if (g == 0)
return r;
if (r == 0)
return 0;
double E_gr = max ((p * ExpectedValue (g - 1, r)) + (q * ExpectedValue (g, r - 1)), (r - g));
return E_gr;
}
double max(double a, double b){
if (a > b)
return a;
else return b;
}
我让它运行30分钟,它仍在运行。 对于小的g和r值,可以非常快速地计算解。我做错了什么?
非常感谢任何帮助!
答案 0 :(得分:4)
你的算法很好,但是你在浪费信息。对于某个对(g, r)
,您可以计算它的ExpectedValue,然后将该信息丢弃。通常使用递归算法记住先前计算的值可以加快 LOT 。
以下代码在眨眼之间运行。例如,对于g = r = 5000
,它会在1秒内计算36.900218
。它记得以前的ExpectedValue(g, r)
计算,以防止不必要的递归和重新计算。
#include <stdio.h>
#include <stdlib.h>
double ExpectedValue(int g, int r, double ***expectedvalues);
inline double max(double, double);
int main(int argc, char *argv[]) {
int g = 50;
int r = 50;
int i, j;
double **expectedvalues = malloc(sizeof(double*) * (g+1));
// initialise
for (i = 0; i < (g+1); i++) {
expectedvalues[i] = malloc(sizeof(double) * (r+1));
for (j = 0; j < (r+1); j++) {
expectedvalues[i][j] = -1.0;
}
}
double EV = ExpectedValue(g, r, &expectedvalues);
printf("%f\n\n", EV);
// free memory
for (i = 0; i < (g+1); i++) free(expectedvalues[i]);
free(expectedvalues);
return 0;
}
double ExpectedValue(int g, int r, double ***expectedvalues) {
if (g == 0) return r;
if (r == 0) return 0;
// did we calculate this before? If yes, then return that value
if ((*expectedvalues)[g][r] != -1.0) return (*expectedvalues)[g][r];
double p = (double) g / (g + r);
double E_gr = max(p * ExpectedValue(g-1, r, expectedvalues) + (1.0-p) * ExpectedValue(g, r-1, expectedvalues), (double) (r-g));
// store value for later lookup
(*expectedvalues)[g][r] = E_gr;
return E_gr;
}
double max(double a, double b) {
if (a > b) return a;
else return b;
}
答案 1 :(得分:2)
在我看来,这是正确的,但却是直截了当的解决方案。
以下是您可以做的事情:
ExpectedValue
我可以提供一些代码示例,但这不公平。
答案 2 :(得分:2)
粗略地说,在球门上添加一个球会使你需要对ExpectedValue
进行的召唤次数加倍(让我们不要对边界条件进行狡辩)。这被称为O(e n ),它可以使地球上最强大的计算机瘫痪。
问题是你一遍又一遍地计算相同的值。保留一张ExpectedValue(r,g)
的表格并随时填写,这样您就不必多次计算相同的值。然后你将在O(n 2 )工作,这要快得多。