【问题标题】:calculate expected cost of final product using atleast k out of n items in c使用 c 中 n 个项目中的至少 k 个计算最终产品的预期成本
【发布时间】:2014-05-03 14:09:55
【问题描述】:

假设我有 4 件物品,我必须至少挑选一件物品才能用它们制作产品。 我的每个项目对应的成本为 Item1 -> 4 , Item2 -> 7 , Item3 -> 2 , Item4 -> 5。我必须找到最终产品的预期成本意味着所有可能组合项目的平均值,例如 if我只使用 1 个项目,那么成本可能是 4 、 7 、 2 、 5 如果我使用 2 个项目,成本将是 4+7 、 4+2 、 4+5 、 7+2 、 7+5 、 2+5同样,使用三个项目的所有组合和使用四个项目的 4 + 2 + 7 + 5 。将所有组合相加并除以没有。的组合给了我最终产品的预期成本。所以我想找到所有这些组合的总和,那么我该怎么做呢??

我认为递归将用于计算这些组合但无法应用???

【问题讨论】:

  • 我也一直在考虑这种算法。但是您能具体说明您使用的是哪种语言吗?

标签: c algorithm


【解决方案1】:

您可以使用位操作,而不是使用递归来生成所有可能的子集。对于给出 4 个项目的示例,有 2^4 个可能的子集。因此,您可以使用 4 位二进制数来表示这 2^4 个子集。二进制数将从 0 计数到 2^4-1=15。对于每个数字,您检查 4 位的状态。如果设置了该位,则该元素包含在该子集中,否则不包含。

您可以以Working Java Program 的形式轻松实现此逻辑。

        int[] arr = {4 , 7 , 2 , 5};
        double ans = 0;
        int numCombinations = (int)Math.pow(2, arr.length);

        // Iterate over all the subsets represented in the form of binary numbers
        for(int i=0; i<numCombinations; i++){
            int sum = 0;

            // check whether a bit is set or not. If the bit is set, then that 
            // number is present in that subset, else it is not present.
            for(int bit=0; bit<arr.length; bit++){
                if( (i & (1<<bit)) != 0){
                    sum += arr[bit];
                }
            }
            ans += (double)sum;
        }

        //Divide by numCombinations-1 as we are not considering the empty subset{}
        System.out.println(ans/(numCombinations-1));

对于给定的情况,这个程序正确地计算出答案为 9.6。

运行时间O(n.2^n)

编辑:更好的解决方案

假设您正在生成 n 个元素的所有子集。现在元素有两种可能。它要么被包含,要么不被包含。因此,假设您拥有所有 n-1 个元素子集。对于所有这些 n-1 个元素子集,您将执行上述两种情况之一,即。您将包含或不包含第 n 个元素。因此,我们可以说如果我们总共有 M 个子集,那么任何元素都会出现 M/2 次​​strong>。

在给定的情况下,M 是 2^n,因为我们正在生成所有子集。所以任何元素都会出现 2^(n-1) 次。

所以所有子集中所有数字的总和将是

所有子集的个数之和 = arr[0] * 2^(n-1) + arr1 * 2^(n-1) + .......arr[n] * 2^ (n-1)

将其除以子集的数量将给出答案。

子集总数 = 2^n - 1。

我们减去 1,因为我们不考虑空子集 {}。

所以对于给定的情况,答案将变为 (4+7+2+5) * 2^(n-1) / (2^n - 1) = 9.6

运行时间:O(n)

【讨论】:

    【解决方案2】:

    这个问题有很多对称性,这意味着你不需要程序来解决它。

    (1) 1 部分有 4 种可能的“产品”
    (2) 有 6 (4*3/2) 个产品,有 2 个零件
    (3) 有 4 个 (4*3*2/(3*2*1) 产品有 3 个零件
    (4) 一个产品有4个部分。

    组合总数 = 15(我假设我们可以忽略“零零件的产品”)。

    现在在每种情况下,每个项目的使用次数都相同:

    对于 (1),您使用每 1/4 的时间
    对于 (2),您使用每 1/2 的时间
    对于 (3),您使用每 3/4 的时间
    对于 (4),你一直在使用它们。

    所以每个部分在 15 个配置中总共使用 1 + 3 + 3 + 1 = 8 个。

    因此“预期成本”为

    (8/15) * (4+7+2+5) = 18 * 8 / 15 = 9.6
    

    编辑你怎么能在没有明确计算的情况下得出8/15这个数字?好吧,您可能会注意到,您可以将可能的组合(使用部分或未使用部分)视为具有四位数字的二进制数(因为有四个部分) - 这已在其他答案中指出。当您列出从 0b00000b1111 的所有二进制数时,您知道每个位置将有相同数量的 1 和 0 - 每个位置 8 个。忽略“不是产品”的0b0000,您会发现每个产品仍然有 8 个 - 因此 15 个中有 8 个。

    【讨论】:

      【解决方案3】:

      如果您将项目的使用表示为整数中的一个设置位,那么您可以简单地从 1 迭代到 15 并使用位操作来确定成本。
      在(伪)C

      cost = 0.0;
      for(i=1;i<=15;++i)
      {
        for(j=0;j<4;++j)
        {
          if(i & (1<<j)) cost += item_cost[j];
        }
      }
      average = cost / 15.0;
      

      编辑

      假设您想在最少数量的项目上设置k 的界限

      n = 0;
      cost = 0.0;
      for(i=1;i<=15;++i)
      {
        sum = 0.0;
        used = 0;
        for(j=0;j<4;++j)
        {
          if(i & (1<<j))
          {
           sum += item_cost[j];
           ++used;
          }
        }
      
        if(used>=k)
        {
          cost += sum;
          ++n;
        }
      }
      average = cost / n;
      

      【讨论】:

      • 但是结果会是(8./15.)*sum(item_cost),所以计算起来会更高效:)(因为在15个组合中,每个项目都被选中了8次)。
      【解决方案4】:

      没有什么可以将您的项目彼此区分开来,并且组合集合是完全对称的,因此在所有可能组合的集合中,每个项目被选择的次数与其他每个项目相同。

      所以我们可以通过将每个项目的成本替换为平均项目成本来简化问题,然后只计算所有组合中选择的项目数和组合总数。这使得组合的平均成本:

      average item cost * total number of items
      -----------------------------------------
            total number of combinations
      

      k = 1的情况下,组合总数为2<sup>n</sup>-1,所有组合中的项目总数为n×2<sup>n-1</sup>

      【讨论】:

      • 我们可以假设项目可以复制吗?
      【解决方案5】:

      你的问题可以用数学方法解决-

      让'n'完全没有。元素和“k”为否。要考虑组合的项目。

      SUM = 数组中所有元素的总和

      COMBINATIONS = 从 n 中选择的 k 个项目,即 (n C k)

      FREQUENCY = 所有组合中每个项目的频率,即 (n-1 C k-1)

      所以解决方案是—— Ans = SUM * FREQUENCY / COMBINATIONS

      简化后- Ans = SUM * k / n

      package com.kvvssut.misc;
      
      public class AverageOfCombinations {
      
          public static void main(String[] args) {
              System.out.println(getAverageOfAllKCombinations(new int[]{4,7,2,5,8}, 3));
          }
      
          private static double getAverageOfAllKCombinations(int[] inputs, int k) {
      
              int n = inputs.length;
              long sum = 0;
              for (int i = 0; i < n; i++) {
                  sum += inputs[i];
              }
      
              double output = 0;
              if (k >= n) {
                  output = sum;
              } else if (k > 0) {
                  double combinations = 1;
                  double divider = 1;
      
                  for (int i = n; i > k; i--) {
                      combinations *= i;
                  }
                  for (int i = 2; i <= k; i++) {
                      divider *= i;
                  }
                  combinations /= divider;
      
                  double frequency = 1;
                  for (int i = n - 1; i > k; i--) {
                      frequency *= i;
                  }
                  divider = 1;
                  for (int i = 2; i < k; i++) {
                      divider *= i;
                  }
                  frequency /= divider;
      
                  output = sum * frequency / combinations;
              }
              return output;
          }
      
      }
      

      如有错误请指正。

      【讨论】:

        猜你喜欢
        • 2018-06-16
        • 2019-06-09
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2016-09-22
        • 1970-01-01
        • 2018-01-10
        • 1970-01-01
        相关资源
        最近更新 更多