在之前的《演算法設計與分析》課程的學習中,我們就接觸到了貪心演算法解決背包問題,當然還有動態規劃法解決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;}
運行結果: