概述
求解最优化问题的算法通常需要经过一系列的步骤,在每个步骤都面临着多种选择。对于许多最优化问题,使用动态规划算法来求解有些杀鸡用牛刀了,可以使用更简单,更高效的贪心算法。
贪心算法在每一步都作出当前看起来最佳的选择,也就是说,他总是做出局部最优的选择,寄希望这样的选择能导致全局最优解,即,贪心算法并不保证能得到最优解。
区间贪心(活动选择问题)
方案一
按活动的结束时间递增排序,每次选择结束时间最早的活动。
import java.util.Arrays;
import java.util.Comparator;
import java.util.LinkedList;
import java.util.Scanner;
public class Main{
static int n;
static LinkedList<Activity>A;
public static void main(String[] args) {
Scanner in=new Scanner(System.in);
n=in.nextInt();
Activity act[]=new Activity[n];
A=new LinkedList<>();
for(int i=0;i<n;i++) {
act[i]=new Activity(in.nextInt(),in.nextInt
(),in.nextInt());
}
Arrays.sort(act, new Comparator<Activity>() {
@Override
public int compare(Activity a1,Activity a2)
{
if(a1.finish>a2.finish)
return 1;
else
return -1;
}
});//升序
//输出排序之后的活动
System.out.printf("i ");
for(int i=0;i<n;i++) {
System.out.printf("%d ",act[i].num);
}
System.out.println();
System.out.printf("s[i] ");
for(int i=0;i<n;i++) {
System.out.printf("%d ",act[i].start);
}
System.out.println();
System.out.printf("f[i] ");
for(int i=0;i<n;i++) {
System.out.printf("%d ",act[i].finish);
}
System.out.println();
Greedy(act);//调用贪心算法
while(!A.isEmpty()) {
System.out.println(A.pop().num);
}
}
private static void Greedy(Activity[] act) {
A.add(act[0]);
int k=0;
for(int m=1;m<n;m++) {
if(act[m].start>=act[k].finish) {
A.add(act[m]);
k=m;
}
}
}
}
class Activity{
int num;
int start;
int finish;
public Activity(int num,int start,int finish) {
this.num=num;
this.start=start;
this.finish=finish;
}
}
方案二
import java.util.Arrays;
import java.util.Comparator;
import java.util.LinkedList;
import java.util.Scanner;
public class Main{
static int n;
static LinkedList<Activity>A;
public static void main(String[] args) {
Scanner in=new Scanner(System.in);
n=in.nextInt();
Activity act[]=new Activity[n];
A=new LinkedList<>();
for(int i=0;i<n;i++) {
act[i]=new Activity(in.nextInt(),in.nextInt
(),in.nextInt());
}
Arrays.sort(act, new Comparator<Activity>() {
@Override
public int compare(Activity a1,Activity a2)
{
if(a1.start<a2.start)
return 1;
else
return -1;
}
});//降序
//输出排序之后的活动
System.out.printf("i ");
for(int i=0;i<n;i++) {
System.out.printf("%d ",act[i].num);
}
System.out.println();
System.out.printf("s[i] ");
for(int i=0;i<n;i++) {
System.out.printf("%d ",act[i].start);
}
System.out.println();
System.out.printf("f[i] ");
for(int i=0;i<n;i++) {
System.out.printf("%d ",act[i].finish);
}
System.out.println();
Greedy(act);//调用贪心算法
while(!A.isEmpty()) {
System.out.println(A.pop().num);
}
}
private static void Greedy(Activity[] act) {
A.add(act[0]);
int k=0;
for(int m=1;m<n;m++) {
if(act[m].finish<=act[k].start) {
A.add(act[m]);
k=m;
}
}
}
}
class Activity{
int num;
int start;
int finish;
public Activity(int num,int start,int finish) {
this.num=num;
this.start=start;
this.finish=finish;
}
}
简单贪心(最大利润问题)
import java.util.*;
public class Main {
static class mooncakes{
int totalPrice;
int amount;
double unitPrice;
}//类
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
int n = scanner.nextInt();
int need = scanner.nextInt();
mooncakes[] moon = new mooncakes[n];
for(int i=0;i<n;i++){
moon[i] = new mooncakes();
moon[i].amount = scanner.nextInt();
}
for(int i=0;i<n;i++){
moon[i].totalPrice = scanner.nextInt();
moon[i].unitPrice = (double)moon[i].totalPrice/moon
[i].amount;
}
Arrays.sort(moon, new Comparator<mooncakes>() {
@Override
public int compare(mooncakes o1, mooncakes o2) {
if(o1.unitPrice<o2.unitPrice) return 1;
else return -1;
}
});//降序
double sum=0;
for(int i=0;i<n;i++){
if(moon[i].amount<need){ //供不应球,继续下一种
sum+=moon[i].totalPrice;
need-=moon[i].amount;
}
else{ //需求在此终止
sum+=moon[i].unitPrice*need;
break;
}
}
System.out.format("%.2f",sum);
}
}
Huffman编码
import java.util.Collection;
import java.util.Collections;
import java.util.LinkedList;
import java.util.Scanner;
public class Main {
private static LinkedList<HufNode> hufList = new
LinkedList<HufNode>();// 容器存放节点值
class HufNode implements Comparable<HufNode> {
int value;
String name;
HufNode Lchild = null;
HufNode Rchild = null;
public HufNode() {
}
public HufNode(String s, int v) {
name = s;
value = v;
}
public HufNode(HufNode l, HufNode r) {
Lchild = l;
Rchild = r;
value = Lchild.value + Rchild.value;
}
@Override
public int compareTo(HufNode node1) {
if (value < node1.value) {
return -1;
} else if (value == node1.value) {
return 0;
} else {
return 1;
}
}
}
// 哈夫曼编码
public static void HufmanCode() {
if (hufList.size() == 1) {
return;
}
while (hufList.size() > 1) {
Collections.sort(hufList);
HufNode node = new Main().new
HufNode(hufList.get(0), hufList.get(1));
hufList.remove();
hufList.remove();
hufList.add(node);
} // 此时hufList中只有一个元素,这就是编码后的哈夫曼
树的根节点
}
// 解码,后序遍历
public static void decode(HufNode n, String code) {
if ((n.Lchild == null) && (n.Rchild == null)) {
System.out.print("元素值为 " + n.name + "
编码为:" + code);
System.out.println();
return;
}
decode(n.Lchild, code + "0");
decode(n.Rchild, code + "1");
return;
}
public static void main(String[] args) {
Scanner in = new Scanner(System.in);
int n = in.nextInt();
for (int i = 0; i < n; i++) {
hufList.add(new Main().new HufNode
(in.next(), in.nextInt()));
}
HufmanCode();
decode(hufList.get(0), "");
}
}
经典背包问题
分数背包问题(贪心算法求解)
import java.util.Arrays;
import java.util.Comparator;
import java.util.Scanner;
public class Main{
public static void main(String[] args) {
Scanner in=new Scanner(System.in);
int n=in.nextInt();
Goods goods[]=new Goods[n];
for(int i=0;i<n;i++) {
goods[i]=new Goods();
goods[i].weight=in.nextInt();
}
for(int i=0;i<n;i++) {
goods[i].value=in.nextInt();
goods[i].price=goods[i].value/goods
[i].weight;
}
Arrays.sort(goods, new Comparator<Goods>() {
public int compare(Goods g1,Goods g2) {
if(g1.price<g2.price) return 1;
else return -1;
}
});
int w=50;
double sum=0;
for(int i=0;i<n;i++){
if(goods[i].weight<w){ //供不应球,继续下一种
sum+=goods[i].value;
w-=goods[i].weight;
}
else{ //需求在此终止
sum+=goods[i].price*w;
break;
}
}
System.out.format("%.2f",sum);
}
}
class Goods{
int weight,value;
float price;
}
0-1背包问题(只能用动态规划解决,贪心算法不能得到最优解)
import java.util.Scanner;
public class Main{
static int n,W;
static int w[];
static int c[];
static int maxn=0;
public static void main(String[] args) {
Scanner in=new Scanner(System.in);
n=in.nextInt();
W=in.nextInt();
w=new int[n];
c=new int[n];
for(int i=0;i<n;i++)
w[i]=in.nextInt();
for(int i=0;i<n;i++)
c[i]=in.nextInt();
dp(0,0,0);
System.out.println(maxn);
}
private static void dp(int index, int sumw, int sumc) {
if(index+1==n)
return;
else {
dp(index+1,sumw,sumc);
if(sumw+w[index+1]<=W) {
if(sumc+c[index+1]>maxn) {
maxn=sumc+c[index+1];//优化
}
dp(index+1,sumw+w[index+1],sumc+c[index+1]);
}
}
}
}