说起来贪心算法是非常简单的,因为按照贪心算法的思维来看,我们是不用刻意去学习的。毕竟我们都很贪呀~但是贪也分等级,不是每个人都能贪出境界。
思想
贪心算法就是在当前情况下找出一个最好的选择,也就是说,它考虑的并不长远,只求当下开心。
例子
贪心算法举例比较多的就是背包问题。假如有这样一个背包,容量为100。一共有五种物品。
物品: 1 2 3 4 5
重量:2 2 6 5 4
价值:6 3 5 4 6
可以任意放进这五种物品,要求放入背包的物品价值尽可能最大,但是不可以超过背包容量。
就像开头说的,贪心也可以贪出不同的境界,按照背包问题来看,我自己把贪心分为三个境界。
第一个境界是瞎子式贪心,这种策略每次挑选都选重量最小的物品。因为我们要的最优解是价值最大,所以,这种策略没有抓住根本问题。
第二个境界是矮子式贪心,因为这个人,虽然知道成为最优解的最重要的条件,但是他也只能顾得上这一个因素,那就是他只关注价值最大的东西,所以这种策略也是有局限性的。
第三个境界是王者式贪心,这在贪心者里算是最强的存在了。因为这人,不仅有了身高,还有了脑子。。。这种策略会计算一下,算出每件物品的单位价值,优先取高的。就像我们平时买东西会考虑一下性价比一样,所以生活中的我们,都当过王者。
代码实现
class Program
{
//0-1背包问题
static void Main(string[] args)
{
int[] w = { 2,2,6,5,4};
int[] v = { 6, 3, 5, 4, 6 };
String[,] str = getPackage(w,v,10);
for (int i = 0; i < str.GetLength(0); i++)
{
for (int j = 0; j < str.GetLength(1); j++)
Console.WriteLine(i+" "+j+" 放入货物重量:"+str[i,j]);
}
Console.Read();
}
static String[,] getPackage(int[] w, int[] v, int maxWeight)
{
int[,] p = new int[w.Length + 1, maxWeight + 1];
String[,] str = new String[w.Length + 1, maxWeight + 1];
for (int i = 0; i < p.GetLength(0); i++)
{
for (int j = 0; j < p.GetLength(1); j++)
{
if (i == 0 || j == 0)
{
p[i, j] = 0;
str[i, j] = "";
}
else
{
if ((j - w[i - 1]) >= 0)//第i件物品的在重量小于等于j时可以放入背包
{
p[i, j] = p[i - 1, j - w[i - 1]] + v[i - 1] > p[i - 1, j] ? p[i - 1, j - w[i - 1]] + v[i - 1] : p[i - 1, j];
str[i, j] = p[i - 1, j - w[i - 1]] + v[i - 1] > p[i - 1, j] ? str[i - 1, j - w[i - 1]] + w[i - 1].ToString() : str[i-1,j];
}
else//第i件物品在重量大于j时不能放入背包,此时的总价值为重量为j-1时的总价值,总货物为不放入第i件物品时的总货物
{
p[i, j] = p[i, j - 1];
str[i, j] =str[i-1,j];
}
}
}
}
return str;
}
}
贪心算法是一种最优子结构的算法,所以有局限性,很多时候不能达到整体最佳。