【问题标题】:Listing the total sum of all possible sums in a set with constraints列出带有约束的集合中所有可能和的总和
【发布时间】:2014-09-12 06:54:00
【问题描述】:

我很想知道以下内容:

给定一个包含 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));
    }
}

【问题讨论】:

  • N
  • We can only remove either the first or the last element with 50% probability 这意味着在每一轮中,你可以得到第一个或最后一个(但总是保证得到 1,就像掷硬币一样)或者你可以选择你能得到什么的机会你选择的是50%?
  • 我们可以选择第一个或最后一个元素,概率是 1/2..是的,我们保证在每一轮都得到一个元素@Pham Trung
  • 没有得到游戏规则,但是解决标题中提到的问题:得到数字的所有幂集(有现有的算法),然后为每个组合检查前提条件。如果成立,计算总和。就是这样。
  • N=1000 如何使用电源

标签: java math recursion probability expectations


【解决方案1】:

这个问题可以通过应用动态规划来解决。

首先,我们有游戏的状态是(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;
  }

【讨论】:

  • 听不懂..你能详细说明一下吗?
  • @rajarshi369 哪一部分你不明白?
  • dp 中的转换
  • @rajarshi369 我们先从全集开始,所以只能取出位置0或者位置N-1的元素,所以,下一个状态只能是(start + 1, end)或(开始,结束 - 1)对吗?和玩家轮流,所以玩家 0 -> 玩家 1 -> 玩家 0...
  • @rajarshi369 我们只需要关心玩家0,所以只在玩家== 0时将值添加到结果中,就是这样!
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-12-30
  • 1970-01-01
相关资源
最近更新 更多