Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/algorithm/10.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 如何将一个数组分成3个部分,每个部分的总和大致相等_C#_Algorithm - Fatal编程技术网

C# 如何将一个数组分成3个部分,每个部分的总和大致相等

C# 如何将一个数组分成3个部分,每个部分的总和大致相等,c#,algorithm,C#,Algorithm,我有一个排列好的数组,我想把它分成3部分,这样它们的和就彼此最接近了 Ex: I have this array: 10, 8, 8, 7, 6, 6, 6, 5 so it'll be divided into 3 part like: p1 {10,8} sum = 18 p2 {8,7,6} sum = 21 p3 {6,6,5} sum = 17 我有这个阵列: 10, 8, 8, 7, 6, 6, 6, 5 因此,它将分为3部分,如: p1{10,

我有一个排列好的数组,我想把它分成3部分,这样它们的和就彼此最接近了

Ex: I have this array: 10, 8, 8, 7, 6, 6, 6, 5 so it'll be divided into 3 part like: p1 {10,8} sum = 18 p2 {8,7,6} sum = 21 p3 {6,6,5} sum = 17 我有这个阵列: 10, 8, 8, 7, 6, 6, 6, 5 因此,它将分为3部分,如: p1{10,8}和=18 p2{8,7,6}和=21 p3{6,6,5}和=17 更新代码:

我建议的方法如下(代码如下):

  • 创建数据结构(集合等)以表示所需的输出部分的数量(在示例3中)
  • 按降序对输入数组排序
  • 迭代输入数组的元素,并针对每个值:
    • 选择一个输出部分以将值放入其中(这应该是当前总体总和最低的输出部分…)
    • 将值添加到选定的输出零件
使用上述逻辑,您将始终添加到具有最低总体值的输出部分(这将有助于保持具有相似总体值的部分)

(在下面的代码示例中,我跳过了数组排序步骤,因为您的示例已经排序)

代码:

//输入数组
int[]inputArray=新的int[]{10,8,8,7,6,6,6,5};
//您想要的零件数量
int numberOfOutputParts=3;
//创建零件结构
List listOfParts=新列表();
对于(int i=0;i
上面使用的Part类的代码(尽管您可以使用更好的代码,如下所示):

公共类部分
{
公共列表值
{
得到;
设置
}
公共整数和
{
得到;
设置
}
/// 
///默认构造函数
/// 
公共部分()
{
值=新列表();
}
公共void AddValue(int值)
{
增加(价值);
CurrentSum+=值;
}
}

原始海报已经有了一个有效的解决方案(注释中有说明),可以将阵列分成两个等额的部分;称之为
split2
。可以使用
split2
构建三部分版本

  • 向数组中添加一个新数字,该数字等于原始数字总和的三分之一
  • 使用
    split2
    将阵列拆分为两部分
  • 一个部件具有添加的编号;移除它
  • 使用
    split2
    将另一部分拆分为两部分
    这就像是NP难的问题,但不是很强的意义上的问题,你们可以有一个O(nK)算法,其中K是你们的输入和的大小,请看,也请看我的答案,但在你们的情况下,你们应该增加另一个维度来处理它

    你能试试我的样品吗,这可能对你有帮助

    我的算法: 1/根据输出数组的数目计算数组数的平均值(exp:value=3)

    2/对阵列数求和,直到和与平均值(以1/计算)相比具有最小间隙

    3/执行步骤2,直到到达数组编号的末尾

    我使用C#3.5进行测试

    using System;
    using System.Collections.Generic;
    using System.ComponentModel;
    using System.Data;
    using System.Drawing;
    using System.Linq;
    using System.Text;
    using System.Windows.Forms;
    using System.Collections;
    
    namespace WindowsFormsApplication2
    {
        public partial class Form2 : Form
        {
            public Form2()
            {
                InitializeComponent();
            }
    
            ArrayList inputValue = new ArrayList();
            int avgValue = 0;
            bool isFinish = false;
            private void button1_Click(object sender, EventArgs e)
            {
                #region Init data
                isFinish = false;
                avgValue = 0;
                inputValue.Clear();
                listBox1.Items.Clear();
                //assum you input valid number without space and in desc sorting order 
                string[] arrNumber = textBox1.Text.Split(new char[] { ',' }, StringSplitOptions.RemoveEmptyEntries);
                int numberOfBreak = 3;
                int record = Convert.ToInt32(arrNumber[0]);//update the record with the maximum value of the array numbers
                for (int i = 0; i < arrNumber.Length; i++)
                {
                    inputValue.Add(Convert.ToInt32(arrNumber[i]));
                }
    
                foreach (object obj in inputValue)
                {
                    avgValue += (int)obj;
                }
                avgValue = avgValue / numberOfBreak;
                #endregion
                int lastIndex = 0;
                while (!isFinish)
                {
                    int index = GetIndex(lastIndex);
                    string sResult = "";
                    for (int i = lastIndex; i <= index; i++)
                    {
                        sResult += inputValue[i].ToString() + "-";
                    }
                    listBox1.Items.Add(sResult);
                    if (index + 1 < inputValue.Count)
                    {
                        lastIndex = index + 1;
                    }
                    sResult = "";
                }
            }
    
            private int GetIndex(int startIndex)
            {
                int index = -1;
                int gap1 = Math.Abs(avgValue - (int)inputValue[startIndex]);
                int tempSum = (int)inputValue[startIndex];
                if (startIndex < inputValue.Count - 1)
                {
    
                    int gap2 = 0;
                    while (gap1 > gap2 && !isFinish)
                    {
                        for (int i = startIndex + 1; i < inputValue.Count; i++)
                        {
                            tempSum += (int)inputValue[i];
    
                            gap2 = Math.Abs(avgValue - tempSum);
                            if (gap2 <= gap1)
                            {
                                gap1 = gap2;
                                gap2 = 0;
                                index = i;
                                if (startIndex <= inputValue.Count - 1)
                                {
                                    startIndex += 1;
                                }
                                else
                                {
                                    isFinish = true;
                                }
                                if (startIndex == inputValue.Count - 1)
                                {
                                    index = startIndex;
                                    isFinish = true;
                                }
                                break;
                            }
                            else
                            {
                                index = i - 1;
                                break;
                            }
                        }
                    }
    
    
                }
                else if (startIndex == inputValue.Count - 1)
                {
                    index = startIndex;
                    isFinish = true;
                }
                else
                {
                    isFinish = true;
                }
                return index;
            }
        }
    }
    
    使用系统;
    使用System.Collections.Generic;
    使用系统组件模型;
    使用系统数据;
    使用系统图;
    使用System.Linq;
    使用系统文本;
    使用System.Windows.Forms;
    使用系统集合;
    命名空间Windows窗体应用程序2
    {
    公共部分类表单2:表单
    {
    公共表格2()
    {
    初始化组件();
    }
    ArrayList inputValue=新的ArrayList();
    int avgValue=0;
    bool isFinish=false;
    私有无效按钮1\u单击(对象发送者,事件参数e)
    {
    #区域初始化数据
    isFinish=false;
    平均值=0;
    inputValue.Clear();
    listBox1.Items.Clear();
    //假设您输入的有效数字不带空格且按desc排序顺序
    string[]arrNumber=textBox1.Text.Split(新字符[]{',},StringSplitOptions.RemoveEmptyEntries);
    int numberOfBreak=3;
    int record=Convert.ToInt32(arrNumber[0]);//使用数组号的最大值更新记录
    for(int i=0;i
    
    int total = 0, partSum = 0, partIndex = 0;
    int noOfParts = 3; //Initialize the no. of parts
    int[] input = { 10, 8, 8, 7, 6, 6, 6, 5 };
    int[] result = new int[noOfParts]; //Initialize result array with no. of locations equal to no. of parts, to store partSums
    foreach (int i in input) //Calculate the total of input array values
    {
        total += i;
    }
    int threshold = (total / noOfParts) - (total / input.Length) / 2; //Calculate a minimum threshold value for partSum
    for (int j = input.Length - 1; j > -1; j--)
    {
        partSum += input[j]; //Add array values to partSum incrementally
        if (partSum >= threshold) //If partSum reaches the threshold value, add it to result[] and reset partSum  
        {
            result[partIndex] = partSum;
            partIndex += 1;
            partSum = 0;
            continue;
        }
    }
    if (partIndex < noOfParts) //If no. of parts in result[] is less than the no. of parts required, add the remaining partSum value
    {
        result[partIndex] = partSum;
    }
    Array.Reverse(result);
    foreach (int k in result)
    {
        Console.WriteLine(k);
    }
    Console.Read();     
    
    int-total=0,partSum=0,partIndex=0;
    int noOfParts=3;//初始化零件号
    int[]输入={10,8,8,7,6,6,6,5};
    int[]result=new int[noOfParts];//初始化结果数组,使位置数等于部件数,以存储pa
    
    using System;
    using System.Collections.Generic;
    using System.ComponentModel;
    using System.Data;
    using System.Drawing;
    using System.Linq;
    using System.Text;
    using System.Windows.Forms;
    using System.Collections;
    
    namespace WindowsFormsApplication2
    {
        public partial class Form2 : Form
        {
            public Form2()
            {
                InitializeComponent();
            }
    
            ArrayList inputValue = new ArrayList();
            int avgValue = 0;
            bool isFinish = false;
            private void button1_Click(object sender, EventArgs e)
            {
                #region Init data
                isFinish = false;
                avgValue = 0;
                inputValue.Clear();
                listBox1.Items.Clear();
                //assum you input valid number without space and in desc sorting order 
                string[] arrNumber = textBox1.Text.Split(new char[] { ',' }, StringSplitOptions.RemoveEmptyEntries);
                int numberOfBreak = 3;
                int record = Convert.ToInt32(arrNumber[0]);//update the record with the maximum value of the array numbers
                for (int i = 0; i < arrNumber.Length; i++)
                {
                    inputValue.Add(Convert.ToInt32(arrNumber[i]));
                }
    
                foreach (object obj in inputValue)
                {
                    avgValue += (int)obj;
                }
                avgValue = avgValue / numberOfBreak;
                #endregion
                int lastIndex = 0;
                while (!isFinish)
                {
                    int index = GetIndex(lastIndex);
                    string sResult = "";
                    for (int i = lastIndex; i <= index; i++)
                    {
                        sResult += inputValue[i].ToString() + "-";
                    }
                    listBox1.Items.Add(sResult);
                    if (index + 1 < inputValue.Count)
                    {
                        lastIndex = index + 1;
                    }
                    sResult = "";
                }
            }
    
            private int GetIndex(int startIndex)
            {
                int index = -1;
                int gap1 = Math.Abs(avgValue - (int)inputValue[startIndex]);
                int tempSum = (int)inputValue[startIndex];
                if (startIndex < inputValue.Count - 1)
                {
    
                    int gap2 = 0;
                    while (gap1 > gap2 && !isFinish)
                    {
                        for (int i = startIndex + 1; i < inputValue.Count; i++)
                        {
                            tempSum += (int)inputValue[i];
    
                            gap2 = Math.Abs(avgValue - tempSum);
                            if (gap2 <= gap1)
                            {
                                gap1 = gap2;
                                gap2 = 0;
                                index = i;
                                if (startIndex <= inputValue.Count - 1)
                                {
                                    startIndex += 1;
                                }
                                else
                                {
                                    isFinish = true;
                                }
                                if (startIndex == inputValue.Count - 1)
                                {
                                    index = startIndex;
                                    isFinish = true;
                                }
                                break;
                            }
                            else
                            {
                                index = i - 1;
                                break;
                            }
                        }
                    }
    
    
                }
                else if (startIndex == inputValue.Count - 1)
                {
                    index = startIndex;
                    isFinish = true;
                }
                else
                {
                    isFinish = true;
                }
                return index;
            }
        }
    }
    
    int total = 0, partSum = 0, partIndex = 0;
    int noOfParts = 3; //Initialize the no. of parts
    int[] input = { 10, 8, 8, 7, 6, 6, 6, 5 };
    int[] result = new int[noOfParts]; //Initialize result array with no. of locations equal to no. of parts, to store partSums
    foreach (int i in input) //Calculate the total of input array values
    {
        total += i;
    }
    int threshold = (total / noOfParts) - (total / input.Length) / 2; //Calculate a minimum threshold value for partSum
    for (int j = input.Length - 1; j > -1; j--)
    {
        partSum += input[j]; //Add array values to partSum incrementally
        if (partSum >= threshold) //If partSum reaches the threshold value, add it to result[] and reset partSum  
        {
            result[partIndex] = partSum;
            partIndex += 1;
            partSum = 0;
            continue;
        }
    }
    if (partIndex < noOfParts) //If no. of parts in result[] is less than the no. of parts required, add the remaining partSum value
    {
        result[partIndex] = partSum;
    }
    Array.Reverse(result);
    foreach (int k in result)
    {
        Console.WriteLine(k);
    }
    Console.Read();     
    
    // calculate total
    total = 0;
    for(i = 0; i != size; ++i) {
       total += array[i];
    }
    
    // partition
    n_partitions = 3;
    current_partition = 1;
    subtotal = array[0];
    for(i = 1; i != size; ++i) {
       if(subtotal + array[i] > total / n_partitions) {
          // start new partition;
          current_partition++;
          subtotal = array[i];
       } else {
          // push to current partition
          subtotal += array[i];
       }
    }