Foo和Bar玩战略游戏

时间:2012-10-06 09:48:34

标签: algorithm

Foo和Bar正在玩战略游戏。在比赛开始时,     有 N个苹果,放在一排(直线)。苹果是     编号从1到N.每个苹果都有特定的价格值。

对于i = 1到N,第i个苹果的价格 pi

在这个游戏中,

球员Foo和酒吧做出了另一种举动。

在每次移动中,玩家执行以下操作:      - 如果只剩下一个苹果,玩家抛硬币即可      头部,玩家将苹果中的第一个苹果当作苹果     目前以直线排成一行,否则,最后一个苹果是     由玩家拍摄。

这里的目标是计算Foo将获得的预期总价值     如果Foo首先播放。

注意

硬币是无偏见的。     头部的概率是0.50,类似的是尾部的概率。     总价格价值=所有苹果的价格总和,Foo将获得。

Example 1:
N=5
Apple price val: 
5 2 3 1 5 

Answer is : 11.00

Example 2:
N=6
7 8 2 3 7 8

Answer : 21.250


Example 3:
N=3
1 4 9

First           Second      Third          Foo Total Val
Foo gets 1  Bar gets 4  Foo gets 9          10
Foo gets 1  Bar gets 9  Foo gets 4          5
Foo gets 9  Bar gets 1  Foo gets 4          13
Foo gets 9  Bar gets 4  Foo gets 1          10

probability 0.5 • 0.5 = 0.25. 
Expected value (Foo)= (0.25 *10 )+ (0.25 *5) + (0.25*13)+ (0.25*10) = 9.500

我写了以下代码:

#include<iostream>
using namespace std;
double calculate(int start,int end,int num,int current);
int arr[2010];
int main()
{
    int T;
    scanf("%d",&T);
    for(int t=0;t<T;t++)
    {
        int N;
        scanf("%d",&N);
        for(int i=0;i<N;i++)
        {
            scanf("%d",&arr[i]);
        }
        printf("%.3lf\n",calculate(0,N-1,N/2+N%2,0));   
    }

    return 0;
}
double calculate(int start,int end,int num,int current)
{
    if(num==current)
        return 0;
    double  value=0;
    value=.5*arr[start]+.5*arr[end]+.5*calculate(start+1,end,num,current+1)+.5*calculate(start,end-1,num,current+1);
    return value;
}

但是上面的代码非常慢,因为约束是apple的价格&lt; = 1000         并且1&lt; = N <= 2000并且有500个测试用例。

如何以有效的方式解决它?

1 个答案:

答案 0 :(得分:1)

你可以做的第一个观察是你不需要calculate的所有四个参数 - 其中两个是冗余的,即它们包含的信息在其他两个参数中已经可用。 (顺便说一句,我不确定性能是唯一的问题 - 我认为你不能正确模拟游戏,也许你应该在一些小的测试用例上尝试它。)

然后,在您删除了不必要的参数并将它们归结为0N - 1的两个整数之后,您应该阅读memoization - 这是一种避免执行此操作的方法多次相同的计算。例如,在计算start = 2, end = 7的答案后,不是每次需要此值时反复进行相同的计算,都可以存储在二维数组的第2行第7列中并将其标记为已找到。这样,您只需计算一次每个子区间的答案,然后将其用作您已知的内容。

这将复杂性降低到O(N^2),这取决于实施和测试机器,可能或者可能不足以传递问题,但是一个良好的开端,并具有教育价值 - 动态编程和memoization经常被使用,如果你没有,你应该学习它们。