/**< 1th exmaple: */
/** \brief
* 一个商人带着一个能装m千克的背包去乡下收购货物,
* \ 现有n种货源,且第i种货物有wi千克,可获利pi元,
* \ 如何收购商品,才能使利润最大,注意此时物品可以拆零。
* \return
* data:
5 10
4 5
2 6
3 4
8 15
5 18
*/
/**< 贪婪算法解决,
收获:对于一个数组内的值,如果要从小到大或者重大到小进行选择,可以开一个choose数组进行存储下标。但这个程序用了O(n^2)的时间复杂度,等好的做法应是开一个结构来存储下标和值,然后进行排序,时间复杂度O(n*lgn),或许还有好的算法吧,这是我目前所知道的较好的一个算法。
/**< 1th exmaple: */
/** \brief
* 一个商人带着一个能装m千克的背包去乡下收购货物,
* \ 现有n种货源,且第i种货物有wi千克,可获利pi元,
* \ 如何收购商品,才能使利润最大,注意此时物品可以拆零。
* \return
* data:
5 10
4 5
2 6
3 4
8 15
5 18
*/
/**< 贪婪算法解决 */
#include <iostream>
using namespace std;
struct infor
{
double weight,value,price;
};
int main()
{
int sum_cap,sum_size;
cout << "输入总的物品数量及背包的容量:\n";
cin >> sum_size >> sum_cap ;
cout << "输入" << sum_size << "件物品的重量及价值:\n";
infor matr[sum_size+1];
int sum_weight=0;
for(int i=1;i<=sum_size;++i)
{
cin >> matr[i].weight >> matr[i].value;
matr[i].price=matr[i].value/matr[i].weight;
sum_weight+=matr[i].weight;
}
if(sum_weight<=sum_cap)
cout << "choose total\n";
else
{
int choose[sum_size+1]; //< choose 为索引表,得到所选物品顺序的同时,又不改变物品原有顺序
for(int i=1;i<=sum_size;++i)
{
int maxi=1;
for(int j=2;j<=sum_size;++j)
if(matr[j].price>matr[maxi].price)
maxi=j;
matr[maxi].price=0; //< 得到最大价值的物体标号后,要把它置为0,防止下次重复选择
choose[i]=maxi;
} //想了一下,choose数组的处理是否也可以称之为数据的离散化,emm,应该是吧!
int k;
double sum=0,sum_value=0; //注意,sum及sum_value的数据类型取double是应该的
for( k=1;k<=sum_size&&sum<=sum_cap;++k)
{
sum+=matr[choose[k]].weight;
sum_value+=matr[choose[k]].value;
}
if(sum!=sum_cap) //有可能sum比总容量还要多,则要去掉最后一件商品的一定数量
{
sum_value-=matr[choose[k-1]].value/matr[choose[k-1]].weight*(sum-sum_cap);
matr[choose[k-1]].weight-=(sum-sum_cap);
}
for(int h=1;h<k;++h)
cout << choose[h] << "th: " << "item choose weight is " << matr[choose[h]].weight << endl;
cout << "sum weights are: " << sum_cap << endl;
cout << "sum values is: " << sum_value << endl;
}
cout << "Hello world!" << endl;
return 0;
}
/**< 2th exmaple: */
/** \brief
* 一个商人带着一个能装m千克的背包去乡下收购货物,
* \ 现有n种货源,且第i种货物有wi千克,可获利pi元,
* \ 如何收购商品,才能使利润最大,注意此时物品不可以拆零。
* \ data : 5 8
3 5 1 2 2
4 5 2 1 3
*
* \ 深度优先搜索算法解决 :
void DFS(int index,int sumweight,int sumvalue):
表示选择第index件物品,已经选择的物品的总重量为sumweight,
已经选择的物品的总价值为sumvalue
*/
/**< 2th exmaple: */
/** \brief
* 一个商人带着一个能装m千克的背包去乡下收购货物,
* \ 现有n种货源,且第i种货物有wi千克,可获利pi元,
* \ 如何收购商品,才能使利润最大,注意此时物品不可以拆零。
* \ data : 5 8
3 5 1 2 2
4 5 2 1 3
*
* \ 深度优先搜索算法解决 :
void DFS(int index,int sumweight,int sumvalue):
表示选择第index件物品,已经选择的物品的总重量为sumweight,
已经选择的物品的总价值为sumvalue
*/
#include <iostream>
#include <cstdio>
#include <vector>
using namespace std;
void DFS(int index,int sumweight,int sumvalue);
const int maxn=101;
int n,v,w[maxn],c[maxn],maxvalue=-1;
vector<int> temp,ans; //ans为最终的最优方案的物品下标,temp为局部最优方案的物品下标
int main()
{
cout << "输入物品的数量,以及背包的容量:\n";
cin >> n >> v;
cout << "输入这些物品的重量:\n";
for(int i=0;i<n;++i)
cin >> w[i];
cout << "输入这些物品的价值:\n";
for(int i=0;i<n;++i)
cin >> c[i];
DFS(0,0,0);
cout << "选择的物品标号为:\n";
for(auto s:ans)
cout << "第" << s+1 << "件" << endl;
cout << "总价值为:" << maxvalue << endl;
return 0;
}
void DFS(int index,int sumweight,int sumvalue)//把选择的物品下标也算出来了
{
if(index==n||sumweight>v) //递归边界
return;
temp.push_back(index);
if(sumweight+w[index]<=v)
{
if(sumvalue+c[index]>maxvalue)
{
maxvalue=sumvalue+c[index];
ans=temp;
}
DFS(index+1,sumweight+w[index],sumvalue+c[index]);//递归式
}
temp.pop_back();
DFS(index+1,sumweight,sumvalue);
}