【貪心算法】揹包問題

在之前的《算法設計與分析》課程的學習中,我們就接觸到了貪心算法解決揹包問題,當然還有動態規劃法解決0-1揹包問題等等。今天我就來分析貪心法解決揹包問題。爲了大家可以理解貪心算法,我先分享一道比較簡單的題目。


問題描述:

給你一個非負數整數n,判斷n是不是一些數(這些數不允許重複使用,且爲正數)的階乘之和,如9=1!+2!+3!,如果是,則輸出Yes,否則輸出No;
第一行有一個整數0

問題分析:

看到這個問題,我並不是一下子就想到了解決辦法,只是參考一些資料。列出前9個數字的階乘。存儲在一個數組中,爲什麼是前9個數呢?因爲n<1000000,而9的階乘就是362880,10!一定大於1000000.具體實現辦法:每次都從9的階乘開始(也就是數組的最後一個數字),如果給出的n大於數組的當前數字,則n減去當前數字;如果n小於當前數字,則遍歷數組前邊的數字,直到n爲0或者是已經到達數組的開始就退出循環.


代碼實現:

#include<iostream>
using namespace std;
bool IsSum(int num)
{
       if (num <= 0)
              return false;
       int  factorialArr[] = { 1,2,6,24,120,720,5040,40320,362880 };
       int index = 8;
       while (num > 0 && index >= 0)
       {
              if (num - factorialArr[index] >= 0)
                     num -= factorialArr[index];
              index--;//由於數據不能重複,所以無論減的結果是否大於0,index都要前移
       }
       if (num == 0)
              return true;
       else
              return false;
}
int main()
{
       int n = 0;
       cin >> n;
       while (n--)
       {
              int num = 0;
              cin >> num;
              if (IsSum(num))
              {
                     cout << "Yes" << endl;
              }
              else
                     cout << "No" << endl;
       }
       system("pause");
       return 0;
}

從上邊的題目,我們大致就可以知道貪心的思想–今朝有酒今朝醉。下邊我們來分析揹包問題。

揹包問題:給出揹包所能裝載的最大重量,給出需要裝進去的物品的重量和價值。每次需要裝入的是單位重量價值最高的物品。由於容量問題,如果不能裝入某一件物品,我們可以根據揹包的剩餘容量和物品的重量,決定裝入物品的多少。揹包問題與0-1揹包的不同之處就是:0-1揹包就是裝就要完全裝入,不能完全裝入就不要裝;揹包問題可以裝入物品的部分。

代碼實現:

#include<iostream>
using namespace std;
#include<cassert>
#include<algorithm>
//揹包問題
struct Object
{
       int _num;//物品的序號
       int _weight;
       int _value;
       float _valuePerWeight;//每重量的價值
};
bool Compare(const Object& l, const Object& r)
{
       return l._valuePerWeight > r._valuePerWeight;
}
void Knapsack(Object objects[], int n,int capacity)
{
       assert(objects && n && capacity);
       int index = 0;
       int value = 0;
       //貪心算法實現
       while (index < n)
       {
              if (objects[index]._weight <= capacity)
              {
                     printf("可以完全裝進去第%d件物品\n", objects[index]._num);
                     capacity -= objects[index]._weight;
                     value += objects[index]._value;
                     ++index;
              }      
              else//裝不下一整件物品的情況
              {
                     float proportion = (float)capacity / objects[index]._weight;
                     printf("只能裝進第%d件物品的%f\n", objects[index]._num, proportion);
                     value += (proportion*objects[index]._value);
                     break;
              }
       }
       printf("揹包所能裝物品的價值總和爲:%d\n", value);
}
int main()
{
       int capacity = 0;//揹包所能承受的容量
       cout << "揹包所能承受的容量>:";
       cin >> capacity;
       int nObjects = 0;
       cout << "需要裝入包的物品數>:";
       cin >> nObjects;//需要裝入包的物品數
       Object* objects = new Object[nObjects];
       cout << "依次輸入每個物品的重量和價值"<<endl;
       for (int i = 0; i < nObjects; ++i)
       {
              objects[i]._num = i + 1;
              cin >> objects[i]._weight >> objects[i]._value;
              objects[i]._valuePerWeight = (float)(objects[i]._value) / (objects[i]._weight);
       }
       sort(objects, objects + nObjects, Compare);
       Knapsack(objects, nObjects,capacity);
       delete[] objects;
       system("pause");
       return 0;
}

運行結果
這裏寫圖片描述

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章