贪婪算法的实现

Implementation of Greedy algorithm

本文关键字:实现 算法 贪婪      更新时间:2023-10-16

>我正在尝试为背包问题实现我自己的贪婪算法版本(允许您将对象的分数添加,而不是将对象作为整体添加

)。我按照以下逻辑编写了以下代码: - 创建了一个名为"profitPerWeight"的数组,其中我存储了所有对象的利润/权重值 - 在"knapSack()"函数中,我检查哪个项目具有最有利可图的价值,并使用另一个名为"getFraction()"的函数检查袋子中物体的多少部分(在我的情况下,袋子容量为 15)。 - 在"getFraction()"函数中,如果物品适合整体或适合哪个分数,我返回 1(例如:如果袋子重量当前为 7 并且物品为 2,我返回 1,因为物品可以放入袋子而不会超过容量:15。如果说重量是 7 并且物品是 9,我返回 9%7,因为只有物品 (2) 的一部分 (9) 可以放入袋子而不会超过允许的容量。 - 然后我在袋子中添加物品的分数,我有另一个数组"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();
}

你的函数double getFraction(int index)有一些缺陷。它不应该将物品的重量与袋容量(MAX)进行比较,而应该将重量与当前剩余容量进行比较。即袋容量 - 袋重量。 但是,我也不确定你为什么要做%(模量),当你应该除以得到分数时。 此外,您将两个整数划分为一个双精度,您需要为此进行转换。 尝试将函数更改为以下内容:

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};