概念(基本思想)
贪心算法:在对问题求解时,总是做出在当前看来是最好的选择。也就是说,不从整体最优上加以考虑,算法得到的是在某种意义上的**局部最优解 ** 。
因此贪心算法不是对所有问题都能得到整体最优解,关键是贪心策略的选择。
步骤
1.把求解的问题分成若干个子问题。
2.对每个子问题求解,得到子问题的局部优解 。
3.把子问题的解局部最优解合成原来解问题的一个解。
特点
贪心算法采用自顶向下,以迭代的方法做出相继的贪心选择,一步步的进行。每做一次贪心选择,就会将所需要解决的问题化为更小的子问题,通过每一步贪心选择,可得到问题的一个最优解。虽然每一步上都要保证能获得局部最优解,因此全局解有时不一定是最优。贪心算法不要回溯 。
问题特征
1.贪心选择性质
每次的选择可以依赖以前作出的选择,但不依赖于后面要作出的选择。
2.最优子结构性质
当一个问题的最优解包含其子问题的最优解时。
存在问题
1、不能保证解是最佳的。因为贪心算法总是从局部出发,并没从整体考虑 ;
2、贪心算法一般不用来解决求最大或最小解 ;
3、贪心算法只能确定某些问题的可行性范围 。
案例
【背包问题】有一个背包,容量是M,有n个物品,物品可以分割成任意大小。要求尽可能让装入背包中的物品总价值最大,但不能超过总容量。其重量跟价值具体情况具体分析。
思路:将物品按照单位重量价值进行排序
代码
package tanxin;
import java.util.Arrays;
import java.util.Scanner;
/**
* @author 奥特曼
* @version 1.0
* @date 2020/8/20 0020 下午 14:31
* 贪心算法,背包问题
*/
public class BeiBao {
static int beibaocapacity = 0;
//总共有几个物品
static int n;
public static void bG(int beibaocapacity, int n, int[] weightArr, int[] valueArr) {
//先计算单位价值权重
float[] pi = new float[n];
//用来存放原先的位置,即先放入第几个物体
int[] index = new int[n];
for (int i = 0; i < n; i++) {
pi[i] = (float) valueArr[i] / weightArr[i];
System.out.println("排序之前:权重" + (i + 1) + ": " + pi[i]);
index[i] = i;
}
BubbleSort(pi, index);
System.out.println();
System.out.println("排序之后权重输出");
for (int i = 0; i < weightArr.length; i++) {
System.out.print(pi[i] + " ");
}
System.out.println();
//将排序好的重量和价值分别保存到数组
int[] w1 = new int[n];
int[] v1 = new int[n];
for (int i = 0; i < n; i++) {
w1[i] = weightArr[index[i]];
v1[i] = valueArr[index[i]];
}
//将物品装入背包
//记录哪些物品已经被装入背包 0 没有装入背包 1 代表已经装入背包
int[] x = new int[n];
int maxValue = 0;
for (int i = 0; i < n; i++) {
if (w1[i] <= beibaocapacity) {
//还可以装的下
x[i] = 1; //表示将该物品装入背包
System.out.println("物品:" + w1[i] + " 被放进了");
maxValue += v1[i];
beibaocapacity -= w1[i];
}
}
System.out.println("总共放下的物品的数量为:" + Arrays.toString(x));
System.out.println("最大价值为:" + maxValue);
}
public static void BubbleSort(float arr[], int[] index) {
int i = 0;
int j = 0;
//判断进行多少趟比较
for (i = 0; i < arr.length - 1; i++) {
//判断进行多少次比较
for (j = 0; j < arr.length - i - 1; j++) {
//判断大小进行交换
if (arr[j] < arr[j + 1]) {
float tmp = arr[j];
arr[j] = arr[j + 1];
arr[j + 1] = tmp;
//将排序后性价比的下标更新为性价比排序后的位置
int tmp1 = index[j];
index[j] = index[j + 1];
index[j + 1] = tmp1;
System.out.println(index[j] + " ");
}
}
}
System.out.println("index排序之后,对应原index");
for (int k = 0; k < arr.length; k++) {
System.out.println(index[k] + " ");
}
}
public static void main(String[] args) {
System.out.println("请输入背包可承受重量(kg),数字:");
Scanner input = new Scanner(System.in);
String W = input.nextLine();
String regex = "[1-9]{1}[0-9]{1,12}";
boolean flag = W.matches(regex);
if (flag) {
beibaocapacity = Integer.parseInt(W);
} else {
System.err.println(W + " 不合法,需要输入全部是数字");
}
System.out.println("请输入有几个物品:");
Scanner input1 = new Scanner(System.in);
n = input1.nextInt();
int[] Warray1 = new int[n];
int[] Varray2 = new int[n];
for (int i = 0; i < n; i++) {
System.out.println("请依次输入第" + (i + 1) + "个物品重量和价值,用逗号隔开:");
Scanner input2 = new Scanner(System.in);
String WandV = input.nextLine();
int mid = WandV.indexOf(",");
String weight = WandV.substring(0, mid);
Warray1[i] = Integer.parseInt(weight);
String value = WandV.substring(mid + 1, WandV.length());
Varray2[i] = Integer.parseInt(value);
}
for (int i = 0; i < n; i++) {
System.out.print(Warray1[i] + " ");
}
System.out.println();
for (int i = 0; i < n; i++) {
System.out.print(Varray2[i] + " ");
}
System.out.println();
BeiBao.bG(beibaocapacity, n, Warray1, Varray2);
}
}