贪心算法 之 装箱问题(可得到最优解的近似解)
1.贪婪准则:
1>贪婪准则设计算法的每一步的最优解(局部最优)
2>贪心准则一旦设好,中途不变
2.贪婪准则并不一定能得到最优解:
装箱问题:
有若干个体积为V的箱子;
有N个物品体积为:v0,v1,v2,v3…….
要求:
将所有的物品装入箱子中,使得打开的箱子最少;
贪婪准则:
1.将所有物品按照体积降序排列;
2.每次取出一个物品(当前没有装入箱子的体积最大的);
3.遍历所有已打开的箱子,放入一个较早打开的箱子,如果放不下便开一个新箱子;
实现(由伪代码描述):
1.存储:
2.类型声明:
物品信息:
typedef struct{
int gnum; //物品编号
int gv; //物品体积
}ElemG;
物品信息集合:假设有n个物品;
ElemG *g;
g=(ELemG *)malloc(n*sizeof(ElemG));
物品信息初始化:
for(int i;i<n;i++){
}
物品节点:
typedef struct node{
int gnum;
struct node *link;
}Goods;
箱子节点:
typedef struct box{
int Remainder;
struct Goods *
struct box *next;
}
算法描述:
1.创建物品信息数组,并初始化;
2.将所以有物品按体积降序排列;
3.装箱;
4.输出;
装箱:
遍历所有已排序的数组;
for(i=0;i<n;i++){
}
for(p=hbox;p&&p->remainder<g[i].gv;p=p->next); 遍历箱子链表
//跑完后,得到要放入的箱子;
if(!p){ //p为^,则需要打开新箱子;(正向建链)
创建箱子节点,初始化箱子。(注意放入第一个箱子的分支)
}
放入物品{
建物品节点;
if(是新箱子){
}
else{
for(q=p->hg;q->next;q=q->next; //找到箱子链表的最后
}
}
代码实现:c代码
/*
装箱问题:
有若干个体积为V的箱子;
有N个物品体积为:v0,v1,v2,v3.......
要求:
将所有的物品装入箱子中,使得打开的箱子最少;
*/
#include <stdio.h>
#include <stdlib.h>
typedef struct{ //物品信息
int Goodsnum;
int gv;
}Goods;
typedef struct nod{ //物品结点
int Goodsnum;
struct nod *next;
}Goodnode;
typedef struct node{ //箱子结点
int boxv;
Goodnode *goodlink;
struct node *next;
}Boxnode;
void print (Goods *a, int n);
void getgoods(Goods *a,int n);
void Sortd (Goods *a,int n);
Boxnode* Putgoods (Goods *a,int n);
void printbox (Boxnode *boxs);
int main (void){
double n=50;
Boxnode *boxs;
Goods* a=(Goods*)malloc(10*sizeof(Goods));
getgoods(a,10);
print(a,10);
Sortd(a,10);
print(a,10);
boxs=Putgoods(a,10);
printbox(boxs);
}
void getgoods (Goods *a,int n){ //输入物品数组
printf("请输入物品信息:");
for(int i=0;i<n;i++){
scanf("%d",&a[i].gv);
a[i].Goodsnum=i+1;
}
}
void Sortd (Goods *a,int n){ //将物品数组按物品的体积排序
Goods t;
for(int i=0;i<n;i++){
for(int j=i+1;j<n;j++){
if(a[i].gv<a[j].gv){
t=a[i];
a[i]=a[j];
a[j]=t;
}
}
}
}
Boxnode* Putgoods (Goods *a,int n){
Boxnode *boxs=NULL,*p,*tail;
Goodnode *gi,*g; //gi用来跑链表 g用来分配单元做节点
for(int i=0;i<n;i++){ //i遍历物品数组
for(p=boxs;p&&p->boxv<a[i].gv;p=p->next); //得到需要放入的箱子p
if(!p){ //需要打开新箱子的情况
p=(Boxnode*)malloc(sizeof(Boxnode)); //创建箱子结点
p->next=NULL;
p->goodlink=NULL;
p->boxv=50;
if(!boxs) { //需要打开第一个箱子的情况
boxs=tail=p;
}
else{
tail=tail->next=p; //挂尾链 挪尾指针
}
}
p->boxv-=a[i].gv; //放入物品,体积减小
for(gi=p->goodlink;gi&&gi->next;gi=gi->next); //遍历物品链表,得到要挂链的位置gi或gi->next
g=(Goodnode*)malloc(sizeof(Goodnode)); //创建了物品结点
g->Goodsnum=a[i].Goodsnum;
g->next=NULL;
if(!gi){ //如果物品链表不存在
p->goodlink=g;
}
else{
gi->next=g;
}
}
return boxs;
}
void printbox (Boxnode *boxs){
Boxnode *i;
Goodnode *j;
int cnt=1;
for(i=boxs;i;i=i->next,cnt++){
printf("这是第%d个箱子:\t",cnt);
for(j=i->goodlink;j;j=j->next){
printf("%d\t",j->Goodsnum);
}
printf("\n");
}
}
void print (Goods *a,int n){
printf("物品信息表:\t");
for(int i=0;i<n;i++){
printf("%d,%d\t",a[i].Goodsnum,a[i].gv);
}
printf("\n");
}