一般的にナップサック問題AFAIKには指数関数的な解決策しかありません。つまり、すべての種類のコインの特定の量があるとします。最も一般的なケースでは、可能なすべての組み合わせを試す必要があります(もちろん全体の重量を超えないようにしてください)。
再帰的アルゴリズムは次のようになります。
const int N = /* type count*/;
const int g_Weight[N] = { ... };
const int g_Value[N] = { ... };
int CalcMinValueFrom(int weight, int i)
{
int valBest = 0, valMy = 0;
if (weight <= 0)
return 0; // weight already reached
if (i >= N)
return -1; // out of coins
while (true)
{
int valNext = CalcMinValueFrom(weight, i+1);
if (valNext >= 0)
{
valNext += valMy;
if (!valBest || (valBest > valNext))
valBest = valNext;
}
valMy += g_Value[i];
weight -= g_Weight[i];
if (valBest && (valBest <= valMy))
return valBest;
}
}
// Returns the minimum value for the given weight
int CalcMinValue(int weight)
{
return CalcMinValueFrom(weight, 0);
}
ただし、特定のケースでは、より良い解決策があります。重量がどのコインの重量よりもはるかに大きい場合は、結果を簡単に概算できます。すべてのコインについて、その「効率」をその価値と重量の比率として定義します。値を最小化するには、「効率」が最も低いコインのみを選択する必要があります。このソリューションは、丸めなどの「エッジ効果」まで正確です(つまり、整数個のコインしか取得できません)。