我很想知道以下内容:
给定一个有N个元素的集合,我和我的朋友正在玩游戏。我总是先行动。 我们只能删除第一个或最后一个元素,每个元素有50%的几率。我们在游戏中进行交替轮换。如果只剩下一个元素,我们可以将其删除。我可以收集的预期金额是多少?
For example:N=2 {10,20} Possible sets that I can collect are {10},{20}.
So expected sum is 0.5*10+0.5*20=15.
我的方法:
由于获得可能总和的概率在所有情况下都相等,我们只需要计算所有可能总和的总和,然后乘以(0.5)^ N / 2.
我尝试使用递归来计算所需的总和:
f(i,j)-computes the sum between i and j recursively
f(i,j)=2*a[i]+func(i,j-2)+func(i+1,j-1)+func(i+1,j-1)+func(i+2,j)+2*a[j]);
Initial call f(1,N)
但这种做法似乎并不奏效。我该怎么办?
完整功能如下:
class CandidateCode {
static long v[][] = new long[1003][1003];
public static long func(int a[], int i, int j) {
if (i == j)
return v[i][j] = a[i];
if (v[i][j] != 0)
return v[i][j];
else {
if (i > j - 2 && i + 1 > j - 1 && i + 2 > j)
return (v[i][j] += 2 * a[i] + 2 * a[j]);
else
return (v[i][j] += 2 * a[i] + func(a, i, j - 2) + func(a, i + 1, j - 1) + func(a, i + 1, j - 1)
+ func(a, i + 2, j) + 2 * a[j]);
}
}
public static void main(String args[]) {
int n;
int a[] = { 0, 6, 4, 2, 8 };
n = a.length - 1;
System.out.println(func(a, 1, 4) / Math.pow(2, n / 2));
}
}
答案 0 :(得分:0)
这个问题可以通过应用动态编程来解决。
首先,我们让游戏的状态为(player ,start, end)
,表示当前玩家,以及原始集中可用的值范围。一开始,我们从玩家0开始,start
为0,end
为N - 1.
表示第一个玩家为0而第二个玩家为1,我们有玩家0的预期值:
if(player == 0){
double result = 0.5*( set[start] + f(1, start + 1,end) ) + 0.5*(set[end] + f(1,start, end - 1));
}else{
double result = 0.5*( f(0, start + 1,end) ) + 0.5*(f(0,start, end - 1));
}
因此,对于每个状态,我们可以将所有计算状态存储在dp[player][start][end]
表中,这会将时间复杂度降低到O(2 * N * N),其中N是集合中的值的数量。
伪代码:
double expectedValue(int player, int start, int end, int[]set){
if(start == end)
if(player == 0)
return set[start];
return 0;
if(already calculated this state)
return dp[player][start][end];
double result= 0;
if(player == 0){
result = 0.5*( set[start] + f(1, start + 1,end) ) + 0.5*(set[end] + f(1,start, end - 1));
}else{
result = 0.5*( f(0, start + 1,end) ) + 0.5*(f(0,start, end - 1));
}
return dp[player][start][end] = result;
}