我正在寻找一种算法来解决以下问题(我将用一个例子来解释):
假设我有10.000美元可用金额以及我可以使用我的金额支付的以下费用:
费用1:1.000 $
费用2:3.000 $
费用3:4.000 $
费用4:5.000 $
部分费用无法支付,因此要么支付全部费用,要么根本不支付。我正在寻找的是一种算法,可以帮助我找到不超过可用金额的成本组合,但另一方面使用大部分或全部可用金额。
在我的例子中,它将是:成本1 +成本3 +成本4。
我还想添加一个参数,该参数确定可以最大限度地融资的成本。如果我在我的例子中说只需支付两笔费用,则会退还费用3和费用4。
我的方法是检查所有可用的组合,总结它们并选择最能使用可用数量的组合。我想知道是否有最简单的方法来找到最佳组合。
答案 0 :(得分:1)
这是一个简单的动态编程问题(Knapsack的一种变体)。状态可以定义为[position] [rest_amount] [how_many_bills_can_be_paid]。下面的递归解决方案:
假设C
是费用数组,memo
初始化为-1:
const int N = 10; //number of notes to pay
int memo[N][M][K]; //remember to initialize it with -1
int func(int cur_index,int rest_amount,int K){
if(cur_index == N){
return 0;
}
int &ret = memo[cur_index][rest_amount][K];
if(ret != -1) return ret; //memoization ensures we won't solve the same sub problem more than once
ret = 0;
if(rest_amount >= C[cur_index] && K > 0 )
ret = func(cur_index+1,cost+C[cur_index],K-1);
ret = max(ret,func(cur_index+1,cost,K);
return ret;
}
答案 1 :(得分:0)
您可以对列表进行排序并选择顶部,直到预算耗尽为止。它也用于垃圾箱包装,并保证在一定的最佳范围内。
答案 2 :(得分:0)
我无法改进您的常规数据解决方案,但是很少有改进可以加快它的速度。
如果总金额N
非常低,则可以使用简单的动态解决方案:
setOfValues
put totalAmount to setOfValues
foreach cost do
foreach amount in setOfValues do
if (amount - cost) > 0 and not exists (amount - cost) in setOfValues
put (amount - cost) to setOfValues
get lowest setOfValues
您可以简单地将其升级到其他要求(例如最高x
费用)。
答案 3 :(得分:0)
几周前我在java中设计了这样的算法。我使用了宽度为N的二进制矩阵,其中N是不同成本的数量,高度为2 ^ N,为我们提供了所有可能的组合。
所以第一项是指您案例中的最低成本。这是一个1000,3000,4000的例子。(你可以展开这个,但我只是想告诉你我是怎么做的。)
宽度= N = 3
高度= 2 ^ N = 8
0 0 0 = 0 + 0 + 0 = 0
1 0 0 = 1000 + 0 + 0 = 1000
0 1 0 = 0 + 3000 + 0 = 3000
1 1 0 = 1000 + 3000 + 0 = 4000
0 0 1 = 0 + 0 + 4000 = 4000
1 0 1 = 1000 + 0 + 4000 = 5000
0 1 1 = 0 + 3000 + 4000 = 7000
1 1 1 = 1000 + 3000 + 4000 = 8000
我有一张包含费用的清单。当我逐行按下矩阵时,我只检查了矩阵上有1的列表。由于成本是排序的,我发现等于或大于总量的行将是最低的。
告诉我你是否理解,我会详细说明!
答案 4 :(得分:0)
你的问题是NP problem;没有已知的解决方案可以保证在可接受的时间范围内找到最佳解决方案。真正找到最佳解决方案的唯一方法是尝试所有可能的解决方案,然后检查哪一个是最佳的。但是,如果你有成千上万的成本,那当然会非常慢。
比上述天真方法更快的所有其他解决方案无法保证找到最佳解决方案。他们可能会找到一个很好的解决方案,但你永远无法确定是否有更好的解决方案。
与以下问题相同:您有一辆可以运输X磅货物的卡车,并且您有不同重量的货物。您的目标是充分利用可用容量。这个也被称为“背包问题”。除了this page上列出的解决方案之外,没有其他更好的解决方案。但是,他们都不能保证最佳结果。