用有限的钱购买物品的算法

Algorithm to purchase items with limited money

本文关键字:算法 钱购买      更新时间:2023-10-16

我有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背包问题。您可以使用以下递归实现来完成此任务。尽管这有重叠的子问题。因此,最好的解决方法是使用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);
    }
}

从主函数中,您可以调用如下方法:

knapsack(No_Item-1,a,desiredVal); 
// Like in your exm : No_Item -> 5 , a[]={7,7,7,5,5}, desiredVal -> 24 
正如其他人所指出的,这个问题是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个项目。你做得再高效不过了。