我正在按照此幻灯片和视频实施NEH算法: http://mams.rmit.edu.au/b5oatq61pmjl.pdf https://www.youtube.com/watch?v=TcBzEyCQBxw
我在测试期间遇到的问题是变量Sorted_list
被更改了,这导致了我预期的不同结果:
这个部分我有问题,但我不知道它改变了什么(我使用断点和观察变量窗口):
for (int i = 0; i < kmsList.Count; i++)
{
for (int j = 0; j < kmsList[i].Length - 1; j++)
{
/*
*
* HERE Sorted_list GET MODIFIED UNEXPECTEDLY
*/
if (i == 0 && j == 0)
kmsList[0][0] = Sorted_list[0][0];
else if (i == 0)
kmsList[0][j] = kmsList[0][j - 1] + Sorted_list[0][j];
else if (j == 0)
kmsList[i][0] = kmsList[i - 1][0] + Sorted_list[i][0];
}
}
完成实施:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace FINAL_NEH
{
class Program
{
static void Main(string[] args)
{
Console.WriteLine("entre the nmbr of jobs : ");
string row = Console.ReadLine();
Console.WriteLine("entre the nmbr of machines : ");
string column = Console.ReadLine();
int job = int.Parse(row.ToString());
int machine = int.Parse(column.ToString());
List<int[]> list = new List<int[]>();
// read the nmbrs and put it in list-----------------------------------------------------
for (int i = 0; i < job; i++)
{
list.Add(new int[machine + 1]);
for (int j = 0; j < machine; j++)
{
list[i][j] = int.Parse(Console.ReadLine());
}
list[i][list[i].Length - 1] = int.Parse((i + 1).ToString()); //Last Elemnt Is Job Number-
}
// show the list----------------------------------------------------------------------------
for (int i = 0; i < job; i++)
{
for (int j = 0; j < machine + 1; j++)
{
Console.Write("\t" + "[" + list[i][j] + "]");
}
Console.WriteLine();
}
// sort the list------------------------------------------------------------------------------
for (int i = 0; i < list.Count; i++)
{
for (int j = i + 1; j < list.Count; j++)
{
int sumI = 0, sumJ = 0;
for (int a = 0; a < list[i].Length - 1; a++)
{
sumI += list[i][a];
}
for (int a = 0; a < list[j].Length - 1; a++)
{
sumJ += list[j][a];
}
if (sumI < sumJ)
{
int[] temp = new int[int.Parse(job.ToString())];
temp = list[i];
list[i] = list[j];
list[j] = temp;
}
}
}
Console.Write("\n\n-----------------after sorting ------------------------------------\n\n");
// shaw the list after sorting------------------------------------------
for (int i = 0; i < job; i++)
{
for (int j = 0; j < machine + 1; j++)
{
Console.Write("\t" + "[" + list[i][j] + "]");
}
Console.WriteLine();
}
// clculate the maxpane of the first 2 jobs---------------------------------------
List<int[]> initMaxpane = new List<int[]>();
initMaxpane.Add((int[])list[0].Clone());
initMaxpane.Add((int[])list[1].Clone());
// calculer maxspan of first jobs..............................................
for (int i = 0; i < initMaxpane.Count; i++)
{
for (int j = 0; j < initMaxpane[i].Length - 1; j++)
{
if (j == 0 && i == 0)
initMaxpane[0][0] = list[i][j];
else if (i == 0)
initMaxpane[0][j] = (int)(initMaxpane[0][j - 1] + list[0][j]);
else if (j == 0)
initMaxpane[i][0] = (int)(initMaxpane[i - 1][0] + list[i][0]);
}
}
for (int i = 1; i < initMaxpane.Count; i++)
{
for (int j = 1; j < initMaxpane[i].Length - 1; j++)
{
if ((initMaxpane[i][j - 1] > initMaxpane[i - 1][j]))
initMaxpane[i][j] = (int)(initMaxpane[i][j - 1] + list[i][j]);
else
initMaxpane[i][j] = (int)(initMaxpane[i - 1][j] + list[i][j]);
}
}
int Cmax = initMaxpane[initMaxpane.Count - 1][initMaxpane[initMaxpane.Count - 1].Length - 2];
Console.WriteLine("\n\n-------the maxpane offirst jobs----------");
for (int i = 0; i < initMaxpane.Count; i++)
{
for (int j = 0; j < initMaxpane[i].Length; j++)
{
Console.Write("\t" + "[" + initMaxpane[i][j] + "]");
}
Console.WriteLine();
}
List<int[]> initMaxpane2 = new List<int[]>();
initMaxpane2.Add(list.ElementAt(1));
initMaxpane2.Add(list.ElementAt(0));
// calculer maxspan of first jobs reverse..............................................
for (int i = 0; i < initMaxpane2.Count; i++)
{
for (int j = 0; j < initMaxpane2[i].Length - 1; j++)
{
if (j == 0 && i == 0)
initMaxpane2[0][0] = list[i][j];
else if (i == 0)
initMaxpane2[0][j] = (int)(initMaxpane2[0][j - 1] + list[0][j]);
else if (j == 0)
initMaxpane2[i][0] = (int)(initMaxpane2[i - 1][0] + list[i][0]);
}
}
for (int i = 1; i < initMaxpane2.Count; i++)
{
for (int j = 1; j < initMaxpane2[i].Length - 1; j++)
{
if ((initMaxpane2[i][j - 1] > initMaxpane2[i - 1][j]))
initMaxpane2[i][j] = (int)(initMaxpane2[i][j - 1] + list[i][j]);
else
initMaxpane2[i][j] = (int)(initMaxpane2[i - 1][j] + list[i][j]);
}
}
int Cmax2 = initMaxpane2[initMaxpane2.Count - 1][initMaxpane2[initMaxpane2.Count - 1].Length - 2];
Console.WriteLine("\n\n-------the maxpane of first jobs (reverse)----------");
for (int i = 0; i < initMaxpane2.Count; i++)
{
for (int j = 0; j < initMaxpane2[i].Length; j++)
{
Console.Write("\t" + "[" + initMaxpane2[i][j] + "]");
}
Console.WriteLine();
}
List<int[]> MaxpaneList = new List<int[]>();
if (Cmax > Cmax2)
{
MaxpaneList.Add((int[])list[1].Clone());
MaxpaneList.Add((int[])list[0].Clone());
}
else
{
MaxpaneList.Add((int[])list[0].Clone());
MaxpaneList.Add((int[])list[1].Clone());
}
List<int[]> bestSequenceList = null;
List<int[]> kmsList = null;
List<int[]> Sorted_list = list.ToList();
int bestCma = 0;
//int maxspan = 0;
for (int jo = 2; jo < job; jo++)
{
for (int ins = 0; ins <= MaxpaneList.Count; ins++)
{
MaxpaneList.Insert(ins, list[jo]);
kmsList = MaxpaneList.ToList();
int Cma = 0;
for (int i = 0; i < kmsList.Count; i++)
{
for (int j = 0; j < kmsList[i].Length - 1; j++)
{
/*
*
* HERE Sorted_list GET MODIFIED UNEXPECTEDLY
*/
if (i == 0 && j == 0)
kmsList[0][0] = Sorted_list[0][0];
else if (i == 0)
kmsList[0][j] = kmsList[0][j - 1] + Sorted_list[0][j];
else if (j == 0)
kmsList[i][0] = kmsList[i - 1][0] + Sorted_list[i][0];
}
}
for (int i = 1; i < kmsList.Count; i++)
{
for (int j = 1; j < kmsList[i].Length - 1; j++)
{
if ((kmsList[i][j - 1] > kmsList[i - 1][j]))
kmsList[i][j] = kmsList[i][j - 1] + Sorted_list[i][j];
else
kmsList[i][j] = kmsList[i - 1][j] + Sorted_list[i][j];
}
}
Cma = kmsList[kmsList.Count - 1][kmsList[kmsList.Count - 1].Length - 2];
Console.WriteLine("\n\n\n------- the maxpane sequence ----------");
for (int i = 0; i < MaxpaneList.Count; i++)
{
for (int j = 0; j < MaxpaneList[i].Length; j++)
{
Console.Write("\t" + "[" + MaxpaneList[i][j] + "]");
}
Console.WriteLine();
}
Console.WriteLine("MAX : " + Cma + "\n\n\n");
if (ins == 0)
{
bestCma = Cma;
}
if (jo == 2 && ins == 0)
{
bestSequenceList = MaxpaneList.ToList();
bestCma = Cma;
}
else
{
if (bestCma > Cma)
{
bestSequenceList = MaxpaneList.ToList();
bestCma = Cma;
}
}
MaxpaneList.RemoveAt(ins);
}
MaxpaneList = bestSequenceList.ToList();
}
Console.ReadLine();
}
}
}
答案 0 :(得分:3)
创建列表&lt;&gt;时(或任何其他容器)来自另一个容器(就像调用list.ToList()时一样),您不会创建容器中所有元素的副本。您可以创建对您要复制的列表中的项目的新引用。在CS的说法中,它是一个浅层副本,而不是一个深层副本。
所以,如果你这样做:
int[] ia = new[] {0, 1, 2, 3, 4};
int[] ib = new[] {5, 6, 7, 8, 9};
List<int[]> la = new List<int[]>() { ia, ib };
List<int[]> lb = la.ToList();
两个列表都引用相同的两个数组,如果你改变一个这样的数组:
la[1][4] = 10;
然后lb [1] [4]也将是10,因为两个列表每个都包含相同的数组。复制列表不会复制列表中的元素。
答案 1 :(得分:3)
问题在于以下代码(代码段):
List<int[]> Sorted_list = list.ToList();
ToList将创建一个新列表,但因为在这种情况下int []是一个引用类型,所以新列表将包含与原始列表相同的数组的引用。
更新新列表中引用的(数组)值也会影响原始列表中的等效值。
kmsList[0][0] = Sorted_list[0][0];
解决方案是创建'list'及其项目的真实副本(在本例中为int []):
List<int[]> Sorted_list = list.ConvertAll(myArray => (int[])myArray.Clone());
这段代码将列表中的所有数组克隆到一个新变量Sorted_list。
解释值和引用类型之间差异的有用链接是:https://msdn.microsoft.com/en-us/library/t63sy5hs.aspx
参考类型
引用类型包含指向另一个保存数据的内存位置的指针。
参考类型包括以下内容: