貪心演算法 之 裝箱問題
貪心演算法 之 裝箱問題(可得到最優解的近似解)
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"); }