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