2017-03-02 80 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時,將其拉出到您的輸出數組中,並用新生成的五個整數集合組成總體。遺傳算法的工作速度比蠻力更快。