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个测试用例。
如何以有效的方式解决它?
答案 0 :(得分:1)
你可以做的第一个观察是你不需要calculate
的所有四个参数 - 其中两个是冗余的,即它们包含的信息在其他两个参数中已经可用。 (顺便说一句,我不确定性能是唯一的问题 - 我认为你不能正确模拟游戏,也许你应该在一些小的测试用例上尝试它。)
然后,在您删除了不必要的参数并将它们归结为0
到N - 1
的两个整数之后,您应该阅读memoization - 这是一种避免执行此操作的方法多次相同的计算。例如,在计算start = 2, end = 7
的答案后,不是每次需要此值时反复进行相同的计算,都可以存储在二维数组的第2行第7列中并将其标记为已找到。这样,您只需计算一次每个子区间的答案,然后将其用作您已知的内容。
这将复杂性降低到O(N^2)
,这取决于实施和测试机器,可能或者可能不足以传递问题,但是一个良好的开端,并具有教育价值 - 动态编程和memoization经常被使用,如果你没有,你应该学习它们。