贪心算法
1.贪心算法步骤:
(1)排序(按照要贪的东西排)
(2)开始贪(随时检查问题约束)
(3)贪完应该返回问题的解(记录最优解)
2.贪心算法的基本要素
(1)贪心选择性质
(2)最优子结构性质
3.贪心算法的证明
(1)贪心的性质决定了第一次贪一个最大的或最小的是能够导致某个最优解的。第一次贪心是可以的
(2)最优子结构,后续可以一直贪。贪完第一次后,问题规模缩小,但问题依然是一个可以贪心的最优解问题。
4.例子
最优装载问题
背包负重问题(贪单价,让单位背包载重的价值最大化原则【物品可分割】)
0—1背包问题(物品不可分割,无法用贪心算法)
活动安排问题(贪结束时间,以期望能留下最大的连续空间)
以最优装载为例:(c语言)
#include<stdlib.h>
#include<time.h>
#include<stdio.h>
const int N=10;
struct box{
int No;//编号
int w;//重量
};
void selectsort(box b[]){//选择排序
for(int i=0;i<N;i++)
for(int j=i;j<N;j++)
if(b[i].w>b[j].w){//应该按什么排序?
box x;//利用临时变量x交换b[i]和b[j]
x=b[i];
b[i]=b[j];
b[j]=x;
}
}
int greedy(box b[],int c)
{
selectsort(b);
int count=0;
for(int i=0;i<N;i++){
if(b[i].w<=c){
c=c-b[i].w;
count++;
printf("集装箱%d,重量%d,可以上船,轮船载重还剩%d,装了%d个箱子了\n",b[i].No,b[i].w,c,count);
}else{
printf("集装箱%d,重量%d,实在装不下了",b[i].No,b[i].w);
return count;
}
}
//先装哪个集装箱?什么时候就不能装了?怎么记录集装箱数量?
//先排序,以此装船,判断是否超重,如果超重,就不装了,返回已装箱子的数量
return count;
}
int main()
{
//srand((unsigned)time(NULL));
int c=rand()%50;//初始化轮船载重量
printf("轮船最大装载重量:%d吨\n",c);
box b[N];//集装箱数组
for(int i=0;i<N;i++)//初始化集装箱数据
{
b[i].No=i;
b[i].w=rand()%10+1;
printf("集装箱%d,重量%d吨\n",b[i].No,b[i].w);
}
printf("最多可装载%d个集装箱\n",greedy(b,c));
return 0;
}