贪心准则:
将问题的每一步抽象出一个公共的最优解。
注意:在一步中不一定能找到最优解
优点:
简单快速,容易想清楚问题
问题描述:
有n和物品,每个物品体积v1, v2, v3……大小不一,但是都小于箱子体积大小V,现在将所有物品都打包装进箱子,要求装完这些物品之后打开的箱子数量尽量小,求打开的箱子数量是多少?
思路:
1.将所有物品按照体积大小降序排列
2.按照箱子打开的顺序,每一次从头遍历箱子结点,看打开的箱子的剩余体积能不能放下当前物品,直到遍历完所有已经打开的箱子还是放不下,就打开一个新的箱子。
图示展示:
运行结果:
代码描述:
#include <stdio.h>
#include <stdlib.h>
#define GOODS_COUNT 10 //定义物品的数量
#define BOX_VOLUME 20 //定义箱子的体积大小
typedef struct goods //物品信息结构
{
int goods_num; //物品号
int goods_volume; //物品体积大小
} ElementGoods;
typedef struct goods_node //物品结点信息
{
int goods_num; //物品号
int goods_volume; //物品体积
struct goods_node *next;
} GoodsLink;
typedef struct box_node //箱子结点
{
int remember; //箱子剩余体积
GoodsLink *goods_head; //物品头结点
struct box_node *next;
} BoxLink;
void init_goods_info(ElementGoods data[]) //初始化物品信息
{
//自定义每个物品体积大小
int temp_vlume[GOODS_COUNT] = {3, 1, 5, 7, 18, 10, 12, 11, 14, 15};
for (int i = 0; i < GOODS_COUNT; ++i)
{
data[i].goods_num = i+1;
data[i].goods_volume = BOX_VOLUME;
data[i].goods_volume = temp_vlume[i];
}
int exchange = 1; //是否排过序标志
ElementGoods temp;
for (int i = 0; i < GOODS_COUNT && exchange; ++i)
{
exchange = 0;
for (int j = 0; j < GOODS_COUNT - i - 1; ++j)
{
if(data[j].goods_volume < data[j + 1].goods_volume)
{
temp = data[j];
data[j] = data[j + 1];
data[j + 1] = temp;
exchange = 1;
}
}
}
}
BoxLink *packing_box(ElementGoods data[])
{
BoxLink *box_head = NULL, *box_tail = NULL, *p = NULL;
GoodsLink *new_goods, *goods_tail = NULL, *q=NULL;
for (int i = 0; i < GOODS_COUNT; ++i)
{
//从头开始找能够放下当前物品体积大小的箱子
p = box_head;
while(p && (p->remember < data[i].goods_volume))
p = p->next;
//是第一个箱子,或者找完了所有已经打开的箱子,放不下当前物品
//需要打开一个新的箱子
if(!p)
{
p = (BoxLink *)malloc(sizeof(BoxLink));
p->remember = BOX_VOLUME;
p->goods_head =NULL;
p->next = NULL;
if(!box_head)
box_head = box_tail = p;
else
box_tail = box_tail->next = p;
}
//生成新的物品
//放进去物品之后,当前箱子体积为减去物品体积后的大小
p->remember -= data[i].goods_volume;
new_goods = (GoodsLink *)malloc(sizeof(GoodsLink));
new_goods->goods_num = data[i].goods_num;
new_goods->goods_volume = data[i].goods_volume;
new_goods->next = NULL;
//找物品尾结点
for(q=p->goods_head; q&&q->next; q=q->next)
;
if(!q)
p->goods_head = new_goods;
else
q->next = new_goods;
}
return box_head;
}
void output_box_info(BoxLink *box_head)
{
BoxLink *ptr = box_head;
GoodsLink *t = NULL;
int i, cnt = 1;
while(ptr)
{
printf("Box %d:\n", cnt++);
printf("\tremember = %d \n", ptr->remember);
printf("\tgoods : ");
t = ptr->goods_head;
i = 1;
while(t)
{
printf("(%d goods num:%d, reamin volume:%d) ",i++, t->goods_num, t->goods_volume);
t = t->next;
}
printf("\n");
ptr = ptr->next;
}
}
int main(int argc, char const *argv[])
{
ElementGoods goods_data[GOODS_COUNT] = { 0 };
BoxLink *box_head;
init_goods_info(goods_data);
box_head = packing_box(goods_data);
output_box_info(box_head);
return 0;
}