我正在尝试为背包问题实现我自己的Greedy算法版本(允许您添加对象的一部分而不是作为整体的必要对象)。
我按照以下逻辑编写了以下代码: - 创建了一个名为'profitPerWeight'的数组,其中我存储了所有对象的利润/权重值 - 在'knapSack()'函数中,我检查哪个项目的利润最高,并检查另一个名为'getFraction()的函数,该对象的哪个部分适合于包(在我的情况下,包容量为15)。 - 在'getFraction()'函数中,如果项目整体适合或者它的哪一部分适合,则返回1(例如:如果包重量当前为7且项目为2,则返回1,因为该项目可以放入包中没有超过容量:15。如果说重量是7而项目是9我返回9%7因为只有项目(9)的一部分(2)可以进入袋子而不超过允许的容量。 - 然后我在包中添加了项目的一部分,我有另一个数组'bagContent []',它为每个对象存储包中所包含的部分。
例如:如果bagContent为= {1,1,0,0,2 / 3}则意味着我存储在包中:obj0,obj1和2/3 * obj4。
这个问题的输出应该是: 1 *前2/3 *秒1 *第三个0 *第四个1 *第五个1 *第六个1 *第七个
但是,当我运行我的解决方案时,我会得到另一个: 1 *前1 *秒1 *第三0 *第四1 *第五* 1第六1 *第七。
正如你所看到的那样,第二个是'1'而不是'2/3':(。我不知道为什么我猜它是小数字的东西,我需要解决。我尝试了一些东西,但他们但也许我的逻辑出现了问题。我对算法不太熟悉:(。请告诉我我做错了什么以及如何纠正这一点。谢谢。代码如下:
// Knapsack problem: Greedy method
// Objects: 1, 2, 3, 4, 5, 6, 7
// Profits: 10, 5, 15, 7, 6, 18, 3
// Weights: 2, 3, 5, 7, 1, 4, 1
// Fill a 15kg knapsack with the objects(they can be divisible) so that the profit is maximum
// Output should be:
// 1*first 2/3*second 1*third 0*fourth 1*fifth 1*sixth 1*seventh
#include <iostream>
#include <iomanip>
using namespace std;
char *objects[] = {"First", "Second", "Third", "Fourth", "Fifth", "Sixth", "Seventh"};
int profits[] = {10, 5, 15, 7, 6, 18, 3};
int weights[] = {2, 3, 5, 7, 1, 4, 1};
double profitPerWeight[7] = {5, 1.3, 3, 1, 6, 4.5, 3};
int bagWeight = 0;
int bagCapacity = 15;
int fraction;
int bagContent[7] = {0,0,0,0,0,0,0};
int itemToAddIndex = 0;
// function that returns the index of most profitable item in 'profitPerWeight[]'
int MaxProfitItem()
{
int index = 0;
int mostPr = profitPerWeight[0];
for(int i=1; i<7; i++)
{
if(profitPerWeight[i] > mostPr)
{
mostPr = profitPerWeight[i];
index = i;
}
}
return index;
}
// function that returns true if the current fraction of an
// item can fit in the bag or false if the
// current fraction of an item cannot fit in the bag
bool itemFits(int index)
{
if(bagWeight + weights[index] <= 15)
return true;
return false;
}
// function that divides an item with a specified fraction
void divideItem(int index, double fraction)
{
weights[index] = weights[index] / fraction;
}
// function that returns which fraction of an item can fit in the bag
double getFraction(int index)
{
double fraction; // the fraction is initially 1
if(itemFits(index))
{
fraction = 1;
}
else
{
fraction = weights[index] % bagCapacity;
}
return fraction;
}
// puts fraction of item in bag and updates capacity&weight of bag
void putInBag(int itemToAddIndex, double fraction)
{
profitPerWeight[itemToAddIndex] = 0; // disegard this so it won't be seen as max next time we look for most valuable item
bagCapacity = bagCapacity - fraction * weights[itemToAddIndex];
bagWeight = bagWeight + fraction * weights[itemToAddIndex];
bagContent[itemToAddIndex] = fraction;
}
// function that solves the problem using greedy approach
void knapSack()
{
while(bagWeight<=15)
{
itemToAddIndex = MaxProfitItem(); // select the most profit/weight valuable item
fraction = getFraction(itemToAddIndex); // see which fraction of it fits in the bag
putInBag(itemToAddIndex, fraction); // put the fraction of item which fits in bag
}
for(int i=0; i<7; i++)
{
cout << *(objects+i) << "*" << bagContent[i] << " ";
}
}
int main()
{
knapSack();
}
答案 0 :(得分:0)
您的功能double getFraction(int index)
有一些缺陷。它不应该将物品的重量与bagCapacity(MAX)进行比较,它应该将重量与当前的剩余容量进行比较,即bagCapacity - bagWeight。但是,我也不确定你为什么要做%(模数),当你应该划分得到分数。另外,你将两个整数分成一个双,你需要为此做一个演员。尝试将功能更改为以下内容:
double getFraction(int index)
{
double fraction; // the fraction is initially 1
if(itemFits(index))
{
fraction = 1;
}
else
{
fraction = (double)(bagCapacity - bagWeight) / (double)weights[index];
}
return fraction;
}
编辑:而且,当您需要分数(或实际小数点)时,您的数组只保留整数。将int bagContent[7] = {0,0,0,0,0,0,0};
更改为double bagContent[7] = {0.0,0.0,0.0,0.0,0.0,0.0,0.0};