貪心法 揹包問題求解

咱們有n種物品,物品j的重量爲wj,價格爲pj。咱們假定全部物品的重量和價格都是非負的。揹包所能承受的最大重量爲Wios

若是限定每種物品只能選擇0個或1個,則問題稱爲0-1揹包問題。能夠用公式表示爲:數組

最大化  \qquad \sum_{j=1}^n p_j\,x_j
受限於  \qquad \sum_{j=1}^n w_j\,x_j \ \leqslant \ W, \quad \quad x_j \ \in \ \{0,1\}

若是限定物品j最多隻能選擇bj個,則問題稱爲有界揹包問題。能夠用公式表示爲:ide

最大化  \qquad \sum_{j=1}^n p_j\,x_j
受限於  \qquad \sum_{j=1}^n w_j\,x_j \ \leqslant \ W, \quad \quad x_j \ \in \ \{0,1,\ldots,b_j\}

若是不限定每種物品的數量,則問題稱爲無界揹包問題
各種複雜的揹包問題總能夠變換爲簡單的0-1揹包問題進行求解函數

如今咱們能夠分爲2類:即物體能夠分割的揹包問題及物體不可分割的揹包問題,把後者成爲0/1揹包問題。spa

 

注:貪心法只能求解可分割的揹包問題,若是不分割,求的不必定是最優解。code

代碼以下:blog

/*********貪婪法求解可分割的揹包問題**************/
#include<iostream>
using namespace std;
typedef struct{
    float p;
    float w;
    float v;
}OBJECT;
OBJECT object[7];
float x[7];
/*輸入:揹包載重量M,存放n個物體的價值p,重量w信息的數組object[]
輸出: n個物體被裝入揹包的份量x[],揹包物體的總價值 
*/
float knapsack_greedy(float M,OBJECT object[],float x[],int n)
{
    int i;
    float m,p=0;
    for(i=0;i<n;i++)
    {
        object[i].v=object[i].p/object[i].w;
        x[i]=0; //解向量賦初值
    }
    mergeSort(object,n); //按關鍵值v的遞減順序排序
    m=M; //揹包的剩餘載重量
    for(i=0;i<n;i++)
    {
        if(object[i].w<=m)
        {
            x[i]=1;
            m-=object[i].w;
            p+=object[i].p;
        }
        else
        {
            x[i]=m/object[i].w;
            p+=object[i].p*x[i];
            break;
        }
    }
    return p;
}



int main()
{
    cout<<"請依次輸入第i個物體的price 和weight"<<endl;
    float a,b;
    
    for(int i=0;i<7;i++)
    {
        cin>>a>>b;
        object[i].p=a;
        object[i].w=b;
    }
    cout<<endl<<"請輸入最大載重量M";
    float M;
    float resultPrice=knapsack_greedy(M,object,x,7);
    cout<<"最大的價值爲 "<<resultPrice<<endl;



}

mergeSort函數以下:排序

#include<iostream>
using namespace std;
#define INFINITE 10000
#define ARRAYSIZE 80
void merge(int a[],int p,int q,int r);

void mergeSort(int a[],int p,int r)
{
    int q;
    if(p<r)
    {
        q=(p+r)/2;
        mergeSort(a,p,q);
        mergeSort(a,q+1,r);
        merge(a,p,q,r);
    }
}

void merge(int a[],int p,int q,int r)
{
    int i,j;
    int n1=q-p+1;
    int n2=r-q;
    //creat array L[1,..n1+1], R[1,..n2+1];
    int *L=(int *)malloc(sizeof(int)*ARRAYSIZE);
    int *R=(int *)malloc(sizeof(int)*ARRAYSIZE);
    for(i=1;i<=n1;i++)
        L[i]=a[p+i-1];
    for(j=1;j<=n2;j++)
        R[j]=a[q+j];
    //哨兵牌
    L[n1+1]=INFINITE;
    R[n2+1]=INFINITE;
    
    i=1;
    j=1;
    for(int k=p;k<=r;k++)
    {
        if(L[i]<=R[j])
        {
            a[k]=L[i];
            i=i+1;
        }
        else
        {
            a[k]=R[j];
            j=j+1;
        }
    }
}

void main()
{
    int n,i;
    cout<<"請輸入數組的大小n";
    cin>>n;
    int *a=(int *)malloc(sizeof(int)*n);

    cout<<"請依次輸入元素的值"<<endl;
    int x;
    for(i=0;i<n;i++)
    {
        cin>>x;
        a[i]=x;
    }
     mergeSort(a,0,n-1);
     cout<<"合併排序後爲"<<endl;
     for(i=0;i<n;i++)
         cout<<a[i]<<ends;
     cout<<endl;
}

        
View Code
相關文章
相關標籤/搜索