1. 程式人生 > >貪心演算法 之 裝箱問題

貪心演算法 之 裝箱問題

貪心演算法  之  裝箱問題(可得到最優解的近似解)

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"); }