C#随机算法直到满足条件

时间:2017-03-02 18:58:13

标签: c# algorithm random

我有以下情况:

  1. 从特定范围生成n个随机数
  2. 汇总所有数字
  3. 检查sum == x(x是用户设置的数字)
  4. if sum != x然后继续运行循环
  5. 如果sum == x,则显示总计为x的随机数列表
  6. 基于这个逻辑,我能够做到这一点,但实现结果需要永远,有没有更好的方法来解决这个问题?

        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;
        }
    

    修改

    我的方案是获取总计为100的随机整数的n组合。组合的数量取自用户的输入。因此,该程序将提供n个可能的组合,总计最多100个。

    可能的组合:

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

3 个答案:

答案 0 :(得分:2)

如果您有固定的金额和固定数量的元素,请将问题视为分区。例如:

#hot_news .active{
     background-color: #034121;
}

示例输出:

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;
        }
    }
}

答案 1 :(得分:0)

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

只要总体中的一个成员总和为100,就将其拉出到输出数组中,并使用新生成的五个整数集组成总体。

遗传算法比蛮力更快地工作。

答案 2 :(得分:-1)

我不明白为什么你会被投票。你的问题很清楚,你已经知道你的算法很糟糕。

我会在两次传球中解决这个问题。第1遍通过确定从每个部分点到达最终答案的方式有多少。第2遍正在选择一条随机路径。

对于第1遍,您将构建一个数组数组。根据您需要他们总结的数量,可以通过多少种方式获得答案? (有关如何执行此操作的更多信息,请搜索动态编程。)

在第2阶段,你继续前进。您知道每个步骤有多少种方法可以完成您的任务,以及您可以选择的每个值的数量。因此,您知道选择每个值的概率。因此,在(0, 1)中选择一个随机值,浏览答案,选择下一个数字,然后继续。

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