貪心演算法應用之一:裝箱問題
阿新 • • 發佈:2018-12-23
關於貪心演算法:
- 即通過保證區域性最優來求得最優解的一種思維。
- 關鍵在於:設定貪心準則。貪心準則一旦確定,中途不能改變。
- 貪心準則不一定能夠求得最優解。
- 學過的運用貪心演算法的最典型例子有:求圖的最小生成樹的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;
}