今天突然蹦出个算法,经试验万节点不足1秒(不含输出代码)。忍不住发了新帖,大家验证一下算法是否正确。以下是源帖问题(http://topic.csdn.net/u/20110420/00/2945B4AF-4681-42C0-9BD1-65A1C3A76F25.html)
------------------------------------------------------------
这是一个小问题,不算难,却有不少大牛甚至大师都研究过这个问题n堆石子摆成一条线。现要将石子有次序地合并成一堆。规定每次只能选相邻的2堆石子合并成新的一堆,并将新的一堆石子数记为该次合并的代价。试设计一个算法,计算出将n堆石子合并成一堆的最小代价。举个例子,比如: 1 2 3 4,有不少合并方法,比如1 2 3 4 => 3 3 4(3) => 6 4(9) => 10(19)
1 2 3 4 => 1 5 4(5) => 1 9(14) => 10(24)
1 2 3 4 => 1 2 7(7) => 3 7(10) => 10(20)括号里面为总代价可以看出,第一种方法的代价最低,现在随便给出n堆石子,用程序算出这个最小合并代价 以下是我的算法代码:
---------------------------------------------------------------
using System;
using System.Collections.Generic;
using System.Text;namespace MergeStone
{
class Program
{
static List<string> _ResultMap = new List<string>();
static List<int> _Stones = new List<int>();
static int _ResultSum = 0;
static void Main(string[] args)
{
//int sum = SetStones(10000);
int sum = SetStones2(new int[]{ 1, 2, 3, 4 });
Separate(_Stones, sum);
PrintStones();
PrintResult();
Console.Read();
} static int SetStones(int n)
{
Random r = new Random();
int result = 0;
int stone;
for (int i = 0; i < n; i++)
{
stone = r.Next(1, 10);
_Stones.Add(stone);
result += stone;
}
return result;
} static int SetStones2(int[] stones)
{
int result = 0;
foreach (int stone in stones)
{
_Stones.Add(stone);
result += stone;
}
return result;
} static void PrintStones()
{
foreach (int stone in _Stones)
{
Console.Write(stone.ToString() + ",");
}
Console.WriteLine();
} static void PrintResult()
{
Console.WriteLine(String.Format("Result Sum IS:{0}\nResult Map IS:", _ResultSum.ToString()));
foreach (string map in _ResultMap)
{
Console.WriteLine(map);
}
} static void Separate(List<int> stones, int sum)
{
if (stones.Count > 1) _ResultSum += sum;
if (stones.Count < 3) return; int half = (sum / 2) + (sum % 2);
int sum1 = 0, i;
string map = string.Empty;
List<int> stones1 = new List<int>();
List<int> stones2 = new List<int>();
for (i = 0; i < stones.Count; i++)
{
stones1.Add(stones[i]);
sum1 += stones[i];
map += stones[i].ToString();
if (i + 2 == stones.Count || sum1 >= half) break;
map += ",";
}
i++;
map += "+";
while (i < stones.Count)
{
stones2.Add(stones[i]);
map += stones[i].ToString();
if (++i < stones.Count) map += ",";
}
_ResultMap.Insert(0, map);
Separate(stones1, sum1);
Separate(stones2, sum - sum1);
}
}
}
------------------------------------------------------------
这是一个小问题,不算难,却有不少大牛甚至大师都研究过这个问题n堆石子摆成一条线。现要将石子有次序地合并成一堆。规定每次只能选相邻的2堆石子合并成新的一堆,并将新的一堆石子数记为该次合并的代价。试设计一个算法,计算出将n堆石子合并成一堆的最小代价。举个例子,比如: 1 2 3 4,有不少合并方法,比如1 2 3 4 => 3 3 4(3) => 6 4(9) => 10(19)
1 2 3 4 => 1 5 4(5) => 1 9(14) => 10(24)
1 2 3 4 => 1 2 7(7) => 3 7(10) => 10(20)括号里面为总代价可以看出,第一种方法的代价最低,现在随便给出n堆石子,用程序算出这个最小合并代价 以下是我的算法代码:
---------------------------------------------------------------
using System;
using System.Collections.Generic;
using System.Text;namespace MergeStone
{
class Program
{
static List<string> _ResultMap = new List<string>();
static List<int> _Stones = new List<int>();
static int _ResultSum = 0;
static void Main(string[] args)
{
//int sum = SetStones(10000);
int sum = SetStones2(new int[]{ 1, 2, 3, 4 });
Separate(_Stones, sum);
PrintStones();
PrintResult();
Console.Read();
} static int SetStones(int n)
{
Random r = new Random();
int result = 0;
int stone;
for (int i = 0; i < n; i++)
{
stone = r.Next(1, 10);
_Stones.Add(stone);
result += stone;
}
return result;
} static int SetStones2(int[] stones)
{
int result = 0;
foreach (int stone in stones)
{
_Stones.Add(stone);
result += stone;
}
return result;
} static void PrintStones()
{
foreach (int stone in _Stones)
{
Console.Write(stone.ToString() + ",");
}
Console.WriteLine();
} static void PrintResult()
{
Console.WriteLine(String.Format("Result Sum IS:{0}\nResult Map IS:", _ResultSum.ToString()));
foreach (string map in _ResultMap)
{
Console.WriteLine(map);
}
} static void Separate(List<int> stones, int sum)
{
if (stones.Count > 1) _ResultSum += sum;
if (stones.Count < 3) return; int half = (sum / 2) + (sum % 2);
int sum1 = 0, i;
string map = string.Empty;
List<int> stones1 = new List<int>();
List<int> stones2 = new List<int>();
for (i = 0; i < stones.Count; i++)
{
stones1.Add(stones[i]);
sum1 += stones[i];
map += stones[i].ToString();
if (i + 2 == stones.Count || sum1 >= half) break;
map += ",";
}
i++;
map += "+";
while (i < stones.Count)
{
stones2.Add(stones[i]);
map += stones[i].ToString();
if (++i < stones.Count) map += ",";
}
_ResultMap.Insert(0, map);
Separate(stones1, sum1);
Separate(stones2, sum - sum1);
}
}
}
if (i + 2 == stones.Count || sum1 >= half) break;
改为
if (i + 2 == stones.Count || sum1 >= half || sum1 + stones[i + 1] > sum - sum1) break;