贪心算法 0-1背包问题 Java
1、 贪心算法的思想:
假设一个问题比较复杂,暂时找不到全局最优解,我们可以考虑把原问题拆分成几个小问题(分而治之思想),分别求每个小问题的最优解,而把这些“局部最优解”叠起来,当作整个问题的最优解。
即:在每一步中,选择目前最优的策略,而不考虑全局是不是最优。
2、 顾眼前
遵循某种规则,不断(贪心地)选取当前最优策略,最终找到最优解。
难点:当前最优未必是整体最优;
3、 贪心算法三步走:
- 第一步:明确到底什么是最优解?
- 第二步:明确什么是子问题的最优解?
- 第三步:分别求出子问题的最优解再堆叠出全局最优解
0-1背包问题(每一个物品,要么选择,要么放弃)
问题描述:
有一个背包,最多能承载150斤的重量,现在有7个物品,重量分别为
[35, 30, 60, 50, 40, 10, 25],它们的价值分别为[10, 40, 30, 50, 35, 40, 30],如果是你的话,应该如何选择才能使得我们的背包背走最多价值的物品?
分析:对于此类问题,对于选择的物品有一个总和限制,比如重量,又希望另一个属性总和最大,比如价值。
贪心算法三步走:
第一步:明确到底什么是最优解?
即在重量限制范围内,价值最大的选择。
第二步:明确什么是子问题的最优解?
子问题定义?认为每次都尽量选择当前价值最高的物品,这就是“局部最优解”。
第三步:分别求出子问题的最优解再堆叠出全局最优解?
- 子问题定义1:使用价值最高的作为标准:
重量:[35, 30, 60, 50, 40, 10, 25]
价值:[10, 40, 30, 50, 35, 40, 30]
选择:
最终的总重量为:50+30+10+40=130
最终的总价值为:50+40+40+35=165
子问题定义2:将当前物品中重量最小的作为最优解;
重量:[35, 30, 60, 50, 40, 10, 25]
价值:[10, 40, 30, 50, 35, 40, 30]
选择:
最终的总重量为:10+25+30+35+40=140
最终的总价值为:40+30+40+10+35=155
- 子问题定义3:每次选择“价值密度”最高的物品;
重量:[35, 30, 60, 50, 40, 10, 25]
价值:[10, 40, 30, 50, 35, 40, 30]
价值密度:[10/35,40/30,30/60,50/50,35/40,40/10,30/25]
选择:
最终的总重量为:10+30+25+50+35=150
最终的总价值为:40+40+30+50+10=170
总结:单位密度这个策略比之前的价值策略和重量策略都要好。
特定的环境,特定的定义方式,每种定义方式只适合特定条件最优。
代码:
import java.util.Scanner;
public class a_0_1背包问题
{
public static int[] zhonliang = { 35, 30, 60, 50, 40, 10, 25 };
public static int[] jiazhi = { 10, 40, 30, 50, 35, 40, 30 };
public static void main(String[] args) {
Scanner sc=new Scanner(System.in);
int zonzhong=sc.nextInt();//总重量
//调用函数
maxJiaZhi(zonzhong);
}
//求价值
private static void maxJiaZhi(int zonzhong) {
//存储累加的重量和价值
int maxZhong=0;
int maxJia=0;
//存放密度
double[] midu=new double[7];
//存放索引的数组
int [] index=new int[7];
for (int i = 0; i < midu.length; i++)
{
midu[i]=(double)jiazhi[i]/zhonliang[i];
index[i]=i;
}
//冒泡排序
for (int i = 0; i < midu.length-1; i++)
{
for (int j = 0; j < midu.length-1-i; j++)
{
if (midu[j]<midu[j+1])
{
double temp=midu[j];
midu[j]=midu[j+1];
midu[j+1]=temp;
//索引跟着交换
int temp1=index[j];
index[j]=index[j+1];
index[j+1]=temp1;
}
}
}
//计算最优解
for (int i = 0; i < index.length; i++)
{
if (zhonliang[index[i]]<=zonzhong)
{
maxZhong+=zhonliang[index[i]];
maxJia+=jiazhi[index[i]];
zonzhong-=zhonliang[index[i]];
}
}
System.out.println("总重量:"+maxZhong);
System.out.println("总价值:"+maxJia);
}
}
输入样例:
150
输出样例:
总重量:150
总价值:170