贪心算法的步骤
- 将优化问题转化成这样一个问题,即先做出选择,在解决剩下的一个子问题
- 证明原问题总是有一个最优解是贪心算法选择得到的,从而说明贪心选择的安全
- 说明在做出贪心选择中,剩下的子问题具有这样的一个特性:如果将子问题的最优解和我所做的贪心选择联合起来,可以得到一个更加负责的动态规划解
剪绳子
给你一个长度为n的绳子,请把绳子剪成m段(n,m都是整数,且大于1),每段绳子的长度即为k【0】,请问k【0】*k【1】…*k【m】的最大乘积是多少?
思路
如果我们按照以下策略剪绳子,则得到的各段绳子的长度的乘积将最大;当n>5的时候,我们尽可能将绳子剪成长度为3的绳子,当剩下的绳子的长度为4时,把绳子剪成长度为2的绳子
贪心算法的核心是通过局部最优解来得到全局最优解,,对于分割问题来说,要是乘积最大,则贪心算法思想应该尽可能剪为长度为3的绳子
public class 贪心算法之剪绳子 {
public static void main(String[] args) {
System.out.println(greedy_cut_rope_1(8));
System.out.println(greedy_cut_rope(8));
}
// 迭代法
public static int greedy_cut_rope_1(int n)
{
if(n<2) {
return 0;
}
if(n==2) {
return 1;
}
if(n==3) {
return 2;
}
//尽可能多地去减长度为3的绳子段
int timesOf3 = n/3;
//当绳子最后剩下的长度为4的时候,不能再去剪去长度为3的绳子段
if(n-timesOf3*3==1) {
timesOf3-=1;
}
int timesOf2 =(n-timesOf3*3)/2;
return (int) (Math.pow(3,timesOf3)*Math.pow(2,timesOf2));
}
// 递归法
public static int greedy_cut_rope(int n)
{
if(n==2) {
return 2;
}
if(n==3) {
return 3;
}
if(n<2) {
return 1;
}
//int timesOf3 = n/3;
if(n==4) {
return 4;
}
return 3*greedy_cut_rope(n-3);
}
}
背包问题
给定N个物品和容量为C的背包,物品i的重量为Wi,其价格为Vi,背包问题是如何选择装入背包的物品总价值最大,装入的物品不能重复装入
- 选择价值最大的物品
- 选择重量最近的物品
- 选择单位重量下价值最大的物品
毫无疑问我们应该选择第三种
public static int knapsackProblem(int[] w, int[] v ,int n, int c){
// 假设物品已按单位重量降序排列
double[] x = new double[10];
int maxValue =0;
int i;
for(i=0;w[i]<c;i++)
{
//将物品 i 装入背包
x[i]=1;
maxValue+=v[i];
// 背包剩余数量
c=c-w[i];
}
//物品i装入一部分
x[i]=(double)c/w[i];
//返回背包获得的价值
maxValue+=x[i]*v[i];
return maxValue;
}
活动选择
有一个需要是使某一资源的n个活动组成的集合S={a1,a2,a3…,an},该资源一次只能被一个活动资源占用,每个活动ai有一个开始时间Si和一个结束时间Fi,且0<=Si<=Fi<unlimited,一旦选择,活动ai就占据半开时间区间[Si,Fi),如果区间[Si,Fi)与 [Sj,Fj)互不重叠,称活动ai与aj是兼容的。活动选择问题就是要选择出一个由互相兼容的问题组成的最大集合。
对于任意一个非空子问题,设am是Sij中具有最早结束时间的活动
fm=min{fk:ak ∈ Sij}
- 活动am在Sij的最大兼容活动子集中被使用
- 子问题Sim为空,所以选择am使子问题SMij为唯一可能非空的子问题
解决子问题时,选择am是一个可被合法调度,具有最早结束时间内的活动,从直觉上来看,这种活动的选择方法是一种的贪婪的技术,他会给后面的待调度任务流下尽可能多的机会,也就是说,此处的贪心选择使得剩下的未调度的时间最大化
public static void greedy_activity_selector(int[] s,int[] f,boolean[] b)
{
int n = s.length-1;
b[1]=true;
int j=1;
for(int i =2;i<=n;i++)
{
if(s[i]>f[j])
{
b[i]=true;
j=i;
}else
b[i]=false;
}
for(int i=1;i<b.length;i++)
System.out.println(b[i]);
}