2017-03-02 82 views
-1

我有以下情形:C#随机算法,直到满足条件

  1. 从一定范围内产生n数字随机数
  2. 总和的所有数字
  3. 检查是否sum == x(x为数字由用户设置)
  4. 如果sum != x然后继续运行循环
  5. 如果sum == x,则显示随机数列表最高达到x

基于这个逻辑,我能够这样做,但它需要永远的实现结果,有没有更好的方法来解决这个问题?

static void Main(string[] args) 
    { 
     Console.WriteLine("starting..."); 
     List<int> checkList = generate(5); 
     while(!checkSum(checkList, 100)) 
     { 
      checkList = generate(5) 
     } 
     Console.WriteLine("done!"); 
    } 


    private static bool checkSum(List<int> n, int sum) 
    { 
     if(n.Sum() == sum) 
     { 
      return true; 
     } 
     else 
     { 
      return false; 
     } 
    } 


    public static List<int> generate(int n) 
    { 
     Random rng = new Random(); 
     List<int> list = new List<int>(); 
     for (int i = 0; i < 5; i++) 
     { 
      //int ran = some random number 
      list.Add(ran); 
     } 

     return list; 
    } 

EDIT

我在这里的情况是,以获得总计为100组合的数量是从输入由用户所采取的随机整数的n组合。所以程序将给出n数目的可能的组合,总结高达100

可能的组合:

  • 25 + 37 + 9 + 20 + 9 = 100
  • 46 + 21 + 13 + 8 + 12 = 100
+0

您的场景是算法(解决方案),而不是问题。这种算法当然很慢,因为它采用了强力方法。你用一个更好的算法试图解决什么问题? – Tim

+4

'它需要永远达到结果'很明显。有一种情况(所有项目= 20)将使您的条件成立。其实20是独家,所以我不知道这是如何完成。 – Jonesopolis

+1

打印出不工作的序列(不仅仅是成功的序列),你会看到代码中的错误。 – Servy

回答

3

如果您有固定金额和固定数量的元素,您可以将问题看作分区。例如:

using System; 
using System.Collections.Generic; 
using System.Linq; 
using System.Text; 
using System.Threading.Tasks; 

namespace PartitionAndAllocateTEst 
{ 
    class Program 
    { 
     static void Main(string[] args) 
     { 
      var rand = new Random(); 
      int desiredTotal = 100; 
      int partitions = 5; 

      for (int i = 0; i < 10; i++) 
      { 
       List<int> result = GetRandomCollection(rand, desiredTotal, partitions); 
       Console.WriteLine(string.Join(", ", result.Select(r => r.ToString()).ToArray())); 
      } 
     } 

     private static List<int> GetRandomCollection(Random rand, int desiredTotal, int partitions) 
     { 
      // calculate the weights 
      var weights = new List<double>(); 
      for (int i = 0; i < partitions; i++) 
      { 
       weights.Add(rand.NextDouble()); 
      } 
      var totalWeight = weights.Sum(); 

      // allocate the integer total by weight 
      // http://softwareengineering.stackexchange.com/questions/340393/allocating-an-integer-sum-proportionally-to-a-set-of-reals/340394#340394 
      var result = new List<int>(); 
      double allocatedWeight = 0; 
      int allocatedCount = 0; 
      foreach (var weight in weights) 
      { 
       var newAllocatedWeight = allocatedWeight + weight; 
       var newAllocatedCount = (int)(desiredTotal * (newAllocatedWeight/totalWeight)); 
       var thisAllocatedCount = newAllocatedCount - allocatedCount; 
       allocatedCount = newAllocatedCount; 
       allocatedWeight = newAllocatedWeight; 

       result.Add(thisAllocatedCount); 
      } 

      return result; 
     } 
    } 
} 

输出示例:

30, 6, 19, 15, 30 
36, 8, 22, 10, 24 
2, 25, 32, 21, 20 
22, 7, 30, 12, 29 
36, 21, 22, 0, 21 
24, 24, 2, 29, 21 
18, 13, 10, 39, 20 
11, 19, 20, 27, 23 
24, 19, 7, 25, 25 
24, 14, 27, 18, 17 
-1

我不明白为什么你被downvoted。你的问题很清楚,你已经知道你的算法不好。

我会在两遍中解决这个问题。第一遍是确定从每个部分点可以得到多少种方式,然后才能得出最终答案。第二遍是选择一条随机路径。

对于通过1,你建立一个数组数组。通过剩下的数字来挑选,根据你需要他们总结的数字,有多少种方法可以得到答案? (搜索动态编程以了解更多关于如何执行此操作的信息。)

在第2遍中,您继续前进。您在每一步都知道完成任务的方式有多少,以及您可以选择的每个值的数量。因此你知道选择每个值的概率。因此,请在(0, 1)中随机选取一个值,查看答案,挑选下一个号码,然后继续。

这个通用策略不仅仅适用于数字。它可以用来生成任何可以使用动态编程技术计数的随机样本。

0

你可以尝试使用遗传算法。例如,从100个随机整数的集合开始。总结每一组。选择50个更好的集合,总和接近100的集合。保持更好的50,转储其他50并用最好的50的调整版本来替换它们。调整将用另一个随机整数替换集合中的一个整数。

每当总体人口总和达到100时,将其拉出到您的输出数组中,并用新生成的五个整数集合组成总体。遗传算法的工作速度比蛮力更快。