我有X钱购买价格为Y [](最多30件商品)的商品,一件商品只能购买一次。
获得您可以花费的最高金额。
例如的
输入:
钱:24
项目数量:5
项目价格:7,7,7,5,5
产出:最高花钱:24(7 + 7 + 5 + 5)
实现这一目标的最佳算法是什么? 我试图制作代码,但似乎非常不理想
#include <iostream>
using namespace std;
int main()
{
int X;
cout << "money: ";
cin >> X;
int Y[30]; //max 30 items
int amount; //item amount
cout << "amount of items: ";
cin >> amount;
cout << "item price: ";
for(int i=1; i<=amount; i++)
{
cin >> Y[i];
}
//sort the price
bool sort = true;
while (sort == true)
{
int temp;
sort = false;
for(int x=amount; x>=2; x--)
{
if(Y[x] < Y[x-1])
{
temp = Y[x];
Y[x] = Y[x-1];
Y[x-1] = temp;
sort = true;
}
}
}
int priceTotal = 0;
int moneyLeft = X;
int maxMoneySpend = 0;
for(int j=0; j<=amount; j++)
{
priceTotal = 0;
moneyLeft = X;
for(int i=amount-j; i>=1; i--)
if(moneyLeft - Y[i] >= 0)
{
moneyLeft -= Y[i];
priceTotal += Y[i];
}
}
if (maxMoneySpend < priceTotal)
{
maxMoneySpend = priceTotal;
}
}
cout << "maximum money spend: " << maxMoneySpend << endl;
return 0;
}
答案 0 :(得分:1)
此问题可归类为经典的0/1背包问题。您可以使用以下递归实现来执行此任务。虽然这有重叠的子问题。 因此,解决它的最佳方法是使用DP(动态编程)。
typedef long long ll;
ll knapsack(ll id, ll a[], ll desiredVal) // array a[] contains the values ....
{
if(desiredVal<=0 || id<0)
return 0;
if(a[id]>desiredVal)
return knapsack(id-1,a,desiredVal);
else {
ll s1 = a[id] + knapsack(id-1,a,desiredVal-a[id]); // taken the weight //
ll s2 = knapsack(id-1,a,desiredVal); // Not taken the weight //
return max(s1,s2);
}
}
从main函数中,您可以调用此方法,如下所示:
knapsack(No_Item-1,a,desiredVal);
// Like in your exm : No_Item -> 5 , a[]={7,7,7,5,5}, desiredVal -> 24
答案 1 :(得分:0)
正如其他人所指出的,这个问题是NP完全的,因此没有有效的解决方案。你的情绪甚至很快,但不幸的是不正确。
你总是从廉价到昂贵的元素。假设你有元素(10,4,4,2,1)和9的数量。你永远不会最终选择4,4,1,这非常适合。原因是你只会在第一个循环中取1.但没有1,你就不能得到一个奇数(所有其他都是偶数)。取1后,你将加上2和4,共7。接下来的4个不合适。当你先拿4分时,你可以选择接下来的4分,但是8分。但是不会达到9分。
无论如何,由于Y的基数最高为30,因此您无法找到最优解的算法。 30对于今天的计算机来说太大了。最佳解决方案是采用Y的所有子集(称为Y的幂集),计算每个成本,并采用其中最昂贵的成本。 30个项目的子集太多了。它可能适用于20个项目。你不能比这更有效率。