上次演算法,講到很多這類型的問題。
遇到有點難度的問題,通常可往窮舉法方向思考,暴力演算法就是那樣非常直覺。
剛好看到網路有個範例,就瞭解一下。
背包問題(Knapsack Problem)
背包問題是關於最佳化的問題,要解最佳化問題可以使用「動態規劃」(Dynamic programming),從空集合開始,每增加一個元素就先求出該階段的最佳解,直到所有的元素加入至集合中,最後得到的就是最佳解。
#include <iostream>
#include <iomanip>
#include <stdio.h>
#include <stdlib.h>
using namespace std ;
/*
背包問題(Knapsack Problem)
背包問題是關於最佳化的問題,
要解最佳化問題可以使用「動態規劃」(Dynamic programming),
從空集合開始,每增加一個元素就先求出該階段的最佳解,
直到所有的元素加入至集合中,最後得到的就是最佳解。
typedef class body object;
*/
class body
{
private:
public:
char name[20];
int size;
int price;
};
int main(void)
{
const int LIMIT = 8; // 重量限制
const int N = 5; // 物品種類
const int MIN = 1; // 最小重量
int item[LIMIT+1] = {0};
int value[LIMIT+1] = {0};
int newvalue, i, s, p;
object a[] =
{
{"李子", 4, 4500},
{"蘋果", 5, 5700},
{"橘子", 2, 2250},
{"草莓", 1, 1100},
{"甜瓜", 6, 6700}
};
/*
for(i = 0; i < N ;i++)
{
cout<<"物件"<<i+1<<"名稱:";
cin>>a[i].name;
cout<<"物件"<<i+1<<"重量:";
cin>>a[i].size;
cout<<"物件"<<i+1<<"價值:";
cin>>a[i].price;
}
*/
cout<<endl;
printf("物品\tkg\t價格\n");
for(i = 0; i < 5 ;i++)
{
printf("%s\t%d\t%d\n", a[i].name, a[i].size, a[i].price);
}
cout<<endl;
cout<<"有一個背包最多可負重8kg,"<<endl;
cout<<"今天有上表幾項物品可選擇,"<<endl;
cout<<"在背包能承受的重量限制之下,"<<endl;
cout<<"請你挑選出總價值最高的組合,"<<endl;
cout<<"請問該組合總值多少?"<<endl<<endl;
for(i = 0; i < N; i++)
{
for(s = a[i].size; s <= LIMIT; s++)
{
p = s - a[i].size;
newvalue = value[p] + a[i].price;
if(newvalue > value[s])// 找到階段最佳解
{
value[s] = newvalue;
item[s] = i;
}
}
}
cout<<"負重 ";
for(i = 0; i <= 8 ;i++)
cout<<setw(2)<<i<<" ";
cout<<endl;
cout<<"value";
for(i = 0; i <= 8 ;i++)
cout<<setw(2)<<value[i]<<" ";
cout<<endl;
cout<<"item ";
for(i = 0; i <= 8 ;i++)
cout<<setw(2)<<item[i]<<" ";
cout<<endl<<endl;
printf("物品\t價格\n");
for(i = LIMIT; i >= MIN; i = i - a[item[i]].size)
{
printf("%s\t%d\n",a[item[i]].name, a[item[i]].price);
}
printf("合計\t%d\n", value[LIMIT]);
cout<<endl<<endl;
system("pause");
return 0;
}