優先隊列式分支限界法-最小重量機器設計問題


問題描述:

設某一機器由n個部件組成,每一種部件都可以從m個不同的供應商處購得。設是從供應商j處購得的部件i的重量,是相應的價格。試設計一個優先隊列式分支限界法,給出總價格不超過d的最小重量機器設計。

[之所以想記錄這個問題,是因為我覺得自己"用各個部件的最小重量作為未來最理想重量"的這個設計還挺特別。其他都是實驗報告中的內容]

算法描述:

算法實現:

#include<stdio.h>
#include<stdlib.h>

struct NodeType
{
    int *mark;    //記錄部件i的供應商
    int preview;    //當前已買部件重量+未來最理想重量
    int now;    //當前考慮買的部件
    int nowd;    //當前已買部件價格
    struct NodeType* next;
};

#define MAXINT 65534;
int doit(int n,int m,int d,int **w,int **c,int *future)
{
    int frist=0;
    while(frist<m&&c[0][frist]>d)
       frist++;
    //找第一個部件的不超過價格上限的供應商frist
    if(frist==m)return 0; 
    //第一個部件的所有供應商的價格都超過價格上限,無法購買

    /*
    構造優先隊列的第一個結點
    */
    struct NodeType *h,*t,*temp;
    h=t=temp=temp=(struct NodeType *)malloc(sizeof(struct NodeType));
    temp->mark=(int *)malloc((sizeof(int))*n);
   temp->preview=future[0]+w[0][frist];    //當前已買部件重量+未來最理想重量
    temp->now=0;        //當前考慮買的部件為部件0
   temp->nowd=c[0][frist]; //當前已買部件價格(部件0在供應商frist處購買的價格)
    temp->mark[0]=frist;    //部件0在供應商frist處購買
    temp->next=NULL;
    for(int i=frist+1;i<m;i++)
    {
        if(c[0][i]<=d)    //若在供應商i處購買部件0的價格沒有超過價格上限(約束剪枝)
        {
            temp=(struct NodeType *)malloc(sizeof(struct NodeType));
            temp->mark=(int *)malloc((sizeof(int))*n);
            temp->preview=future[0]+w[0][i];//當前已買部件重量+未來最理想重量
            temp->now=0;   //當前考慮買的部件為部件0
            temp->nowd=c[0][i]; //當前已買部件價格(部件0在供應商i處購買的價格)
            temp->mark[0]=i;    //部件0在供應商i處購買
            temp->next=NULL;
            t->next=temp;
            t=t->next;
        }
    }
    int realmin=MAXINT;    //記錄最小重量
    int *markmin;
    markmin=(int *)malloc((sizeof(int))*n);
  //記錄部件i的供應商markmin[i]
    struct NodeType *minr,*minp,*r,*q;
    while(h!=NULL)
    {
    /*
    找到隊列中重量最小的結點作為擴展結點(minp)
    */
        int min=realmin;//-
         r=q=h; 
        while(q!=NULL)
        {        
            if(q->preview<min)
            {
                min=q->preview;
                minr=r;
                minp=q;
            }
            r=q;
            q=q->next;
        }
        for(int i=0;i<m;i++)
        {
            if(minp->nowd+c[minp->now+1][i]<=d)
            //若已買部件價格加上在供應商i處購買
       //部件minp->now+1的價格小於等於價格上限
            {
                temp=(struct NodeType *)malloc(sizeof(struct NodeType));
                temp->mark=(int *)malloc((sizeof(int))*n);
            /*
            當前已買部件重量+未來最理想重量
            */
                temp->preview=0;
                for(int j=0;j<(minp->now+1);j++)
                    temp->preview+=w[j][minp->mark[j]];    
          //先計入之前已買的部件的重量
                temp->preview+=w[minp->now+1][i];    
          //在計入當期在供應商i處購買部件minp->now+1的重量
                temp->preview+=future[minp->now+1];    
          //最后計入未來最理想的重量
                temp->now=minp->now+1;    
          //當前考慮買的部件為部件minp->now+1 temp->nowd=minp->nowd+c[minp->now+1][i];        //當前之前已買部件價格+在供應商i處購買部件           //minp->now+1的價格 /* 記錄之前已買部件的供應商+當前部件的供應商i */ for(int j=0;j<(minp->now+1);j++) temp->mark[j]=minp->mark[j]; temp->mark[minp->now+1]=i; temp->next=NULL; if(temp->now+1==n&&temp->preview<realmin)           //若當前考慮的部件已經是最后一個部件,           //且在供應商i處購買這個部件, //能夠使得現在部件總重量優於當前求解出的最優值 { /*記錄最優值和最優解*/ realmin=temp->preview; for(int j=0;j<n;j++)markmin[j]=temp->mark[j]; free(temp); } else { //若當前考慮的部件並非最后一個部件,將此結點加入隊列 t->next=temp; t=t->next; } } } if(minp==h)//拓展結點為頭結點 { h=h->next; free(minp);//將拓展結點釋放 } else //拓展結點非頭結點 { minr->next=minp->next; free(minp);//將拓展結點釋放 } /* 如果當前隊列中的結點的最理想重量大於已經求出的最優解,則將該結點釋放 */ while(h->preview>=realmin&&h!=t) { q=h; h=h->next; free(q); } if(h->preview>=realmin) { free(h); h=NULL; } } /* 輸出最優值及最優解 */ printf("%d\n",realmin); for(int i=0;i<n;i++)printf("%d ",markmin[i]+1); return 0; } int main() { int n,m,d; scanf("%d %d %d",&n,&m,&d);//部件數,供應商數,價格上限 int ** c; c=(int **)malloc((sizeof(int *))*n); for(int i=0;i<m;i++) c[i]=(int *)malloc((sizeof(int))*m); for(int i=0;i<n;i++) for(int j=0;j<m;j++) scanf("%d",&c[i][j]); //在供應商j處購買部件i的價格c[i][j] int ** w; w=(int **)malloc((sizeof(int *))*n); for(int i=0;i<m;i++) w[i]=(int *)malloc((sizeof(int))*m); for(int i=0;i<n;i++) for(int j=0;j<m;j++) scanf("%d",&w[i][j]); //在供應商j處購買部件i的重量w[i][j] int * future; future=(int *)malloc((sizeof(int))*n); for(int i=0;i<n;i++) { int min=MAXINT; for(int j=0;j<m;j++ ) if(min>w[i][j]) min=w[i][j]; future[i]=min; } for(int i=0;i<n-1;i++) { future[i]=0; for(int j=i+1;j<n;j++) future[i]+=future[j]; } future[n-1]=0; //購買完部件i后剩余部件的最理想重量 doit(n,m,d,w,c,future); //優先隊列分支限界算法 return 0; }

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM