关于贪心算法:
- 即通过保证局部最优来求得最优解的一种思维。
- 关键在于:设置贪心准则。贪心准则一旦确定,中途不能改变。
- 贪心准则不一定能够求得最优解。
- 学过的运用贪心算法的最典型例子有:求图的最小生成树的Prim算法与Kruskal算法以及求图的单源最短路径的Dijkstra算法。
装箱问题
问题描述:
已知条件:
有n个体积互不相同的物品,其体积为{vi|1< i< n}。
有若干个体积为V的箱子;
问题要求
将所有物品全部放入箱子中,使打开的箱子数最少。要求输出打开的箱子数。
确定贪心准则
- 将所有物品按体积降序排列
- 按顺序取出每一个物品,即当前体积最大的物品,将其放入所有能放下的箱子中较早打开的箱子。
存储结构分析:
- 物品信息:标号+体积====存储结构:动态分配的结构体数组;
- 箱子信息:剩余容量,存放的物品,下一个箱子的位置====存储结构:链表,物品结点用结构体表示;
算法描述:
- 初始化;
箱子体积,物品个数,每个物品的体积。 - 将所有物品按降序排列;
- 物品装箱;
- 得到所用箱子个数。
==============简单粗暴上代码好了~~(>_<)~~==============
代码实现
#include<stdio.h>
#include<stdlib.h>
#define V 30
//物品信息声明:物品编号与物品体积
typedef struct{
int gno;
int gv;
}GInfor;
//物品结点类型声明
typedef struct gnode{
int gno;
struct gnode *next;
}GNode;
//箱子结点类型声明
typedef struct bnode{
int remainder;
GNode *firstg;
struct bnode *next;
}BNode;
//对物品信息进行降序排列
void SortD(GInfor *g,int n)
{
int i,j;
GInfor t;
for(i=0;i<n-1;i++)
{
for(j=i+1;j<n;j++)
{
if(g[j].gv>g[i].gv)
{
t=g[j];
g[j]=g[i];
g[i]=t;
}
}
}
}
BNode *PackingBox(GInfor *g,int n)
{
BNode *h=NULL;
BNode *p=NULL;
BNode *tail=NULL;
GNode *newg=NULL;
int i;
for(i=0;i<n;i++)
{
for(p=h;p&&p->remainder<g[i].gv;p=p->next);
if(p==NULL)
{
//需要开新箱子
p=(BNode *)malloc(sizeof(BNode));
p->remainder=V;
p->firstg=NULL;
p->next=NULL;
if(!h)
//因为无头结点需要开新箱子
h=tail=p;
else
{
//因为现有的所有箱子剩余容积均不够需开新箱子
tail=tail->next=p;
}
}
//向确定要放入物品的箱子(不论新旧)放入物品
newg=(GNode *)malloc(sizeof(GNode));
newg->gno=g[i].gno;
newg->next=p->firstg;
p->firstg=newg;
printf("the thing's v is %d",g[i].gv);
p->remainder-=g[i].gv;
}
return h;
}
int main(void)
{
int Gnum,i,Bnum;
GInfor *g=NULL;
BNode *hBox=NULL;
BNode *p=NULL;
printf("Please input the number of things");
scanf("%d",&Gnum);
//创建动态数组存放所有物品信息
g=(GInfor *)malloc(Gnum*sizeof(GInfor));
for(i=0;i<Gnum;i++)
{
printf("Please input the volume of %d thing",i+1);
scanf("%d",&g[i].gv);
g[i].gno=i+1;
}
//调用排序函数
SortD(g,Gnum);
//调用装箱函数
hBox=PackingBox(g,Gnum);
//统计所用的箱子数
for(Bnum=0;hBox;hBox=hBox->next,Bnum++);
printf("The number of box is:%d",Bnum);
return 0;
}