TLDR :(第1部分)需要打印出最佳的重量组合以达到目标体重。 (第2部分)不知道选择什么方法。 (第3部分)另外,递归不是我的朋友。
我不是要求解决方案,我只是在寻找方向。
第1部分 一些文字首先。
该计划的输入是:
总是必须有一个权重= 1,所以所有权重都可以精确组合。 我应该打印出最佳的权重组合,例如
第2部分
我想到的第一件事是无界背包问题,我将权重的所有值设置为“1”,然后我会在背包中寻找最低的值。问题是,当我想找到一篇优秀的文章/代码/视频/无论如何理解它时,我的编程技巧都没有达到那个水平,我的谷歌搜索技能也让我失望。
然后有人指出了改变生活的问题。问题是它通常使用一个数组,我期待非常大的数字,我不能分配一个size =目标权重的数组。此外,如果我不仅要求尽可能最低的权重数量,而且要确切的数量,那么它似乎需要相当多的魔力。
我现在的解决方案,好吗?
(对于权重= 1,3,7,10和目标= 14,贪婪会给我1 x 10 + 1 x 3 + 1 x 1,在第三步之后我会得到(0 x 10 +)2 x 7)
我来了只有我需要在递归函数之外重复这一点(就像我一直在做,直到我意识到它仍然没有给我正确的结果)但我需要将循环移动到递归函数中。
第3部分
这就是我现在部分代码的外观:
for ( i = 0; i < weights_cnt; i ++ )
for ( j = 0; j <= weight / *(weights + i); j ++ )
{
*counter = 0;
if ( (res = greedyMagicImproved(weights + i, weight / *(weights + i) - j, weight, counter, min)) == 0 || min > *counter ) break;
else min = *counter;
}
我知道这是一团糟。 (我写过的第一个递归函数,对不起)
int greedyMagicImproved (int * weights, int limit, int weight, int * counter, int min)
{
if ( *counter > min ) return 0;
else if ( weight % *weights == 0 )
{
printf ("%d * %d\n", limit, *weights);
*counter += limit;
return *counter;
}
else if ( weight == 0 ) return *counter;
else if ( weight / *weights )
{
printf ("%d * %d + ", limit, *weights);
*counter += limit;
return (greedyMagicImproved(weights + 1, (weight - *weights * limit) / *(weights + 1), (weight - *weights * limit) % *weights, counter, min));
}
else return greedyMagicImproved(weights + 1, weight / *(weights + 1), weight, counter, min);
}
这个产生这样的东西:
Number of weights:
8
Actual weights of weights:
1 2 4 5 10 20 60 95
Weights to be composed:
124
GREEDY = 1 * 95 + 1 * 20 + 1 * 5 + 1 * 4
IMP = 1 * 95 + 1 * 20 + 1 * 5 + 1 * 4
2 * 60 + 1 * 4
6 * 20 + 1 * 4
... some more irrelevant results I'll deal with later
28
GREEDY = 1 * 20 + 1 * 5 + 1 * 2 + 1 * 1
IMP = 1 * 20 + 1 * 5 + 1 * 2 + 1 * 1
1 * 20 + 1 * 5 + 1 * 2 + 1 * 1
1 * 20 + 1 * 5 + 1 * 2 + 1 * 1
2 * 10 + 1 * 5 + 1 * 2 + 1 * 1
5 * 5 + 1 * 2 + 1 * 1
... some more results as well
虽然我在第一种情况下看到了正确的结果,但我没有在第二种情况下。 所以基本上,我的问题是:我是否应该尝试将循环部分移动到递归中(并且基本上将它再次写入,因为我不知道该怎么做)或者我应该去窃取/打包并进行更改?
答案 0 :(得分:0)
这是DP配方:
让w[i]
,i=0,1,...p
为硬币重量,f(t,i)
为仅使用t
w[k]
达到目标k >= i
所需的硬币数量}}。如果没有可能的方法进行更改,那么f(t,i)
就是无限的。有了这个我们知道
f(t,i) = min_{n} [ n + f(t - n * w[i], i + 1) ]
在英语中,要仅使用硬币i, i+1, ... p
以最少的硬币击中目标,请选择硬币n
的所有可能数量i
,然后使用相同的DP进行更改剩余金额仅使用硬币i+1,i+2,...
,最后选择产生最小值的解决方案。
基本情况是常识。例如f(0,_) = 0
。你不需要任何硬币来达到零目标。
如果T是问题目标,那么答案将是f(T,0)。
由于您不想要答案,我会让您将其转换为代码。如果权重按降序排序,你很可能会得到更快的答案。