この問題で使用される可能性のあるサブセット合計を生成するプログラムを作成しました。
$1 コインが 3 枚、$2 コインが 2 枚、$5 コインが 3 枚、$10 コインが 1 枚あるとします。これらのコインから $10 を得る方法は 4 つあります。$X1 コインが n1 枚、$X2 コインが n2 枚.... nm $Xm 枚ある場合、これらの限られた数のコインから $X を取得するには、何通りの方法がありますか?
{ X1, X1..... X1, X2, X2.......... X2, ..., ..., ........... .., Xm, Xm... Xm} を実行し、サブセットの合計を実行すると、確かに $X の結果が得られます。しかし、セット {n1, n2, n3.... nm} 、 {X1, X2, X3.... Xm} を使用する方法が見つかりませんでした。ナップザック問題の一種だと友達に言われましたが、どうしてかはわかりません。
これは私が書いたものの部分的なコードです:
ways[0]=1, mylim=0;
for(i=0;i<count;i++){
if(mylim+coins[i]<=LIMIT) mylim+=coins[i];
else mylim=LIMIT;
for(j=mylim; j>=coins[i];j--){
ways[j]=(ways[j]+ways[j-coins[i]])%MOD;
}
}
もう少し丁寧に説明していただけると助かります。
編集:この質問は、コンピューター サイエンスの stackexchange に適していますが、私の古い質問なので、ここで編集しています。
この問題は、包含除外の原則で解決できます。コインの値は固定されているが、各コインの数はクエリごとに異なる場合に便利です。
way [v]が$x1、$x2、.. $xmで$vを作成する方法であり、それぞれが必要な回数だけ使用されるとします。ここで、 $x1 の n1 個のみを使用している場合、少なくとも( n1 + 1) 個の $x1 (実際には [ v - (n1 + 1)x1 ] の方法) を使用して構成を減算する必要があります。さらに、$x2のn2個だけを使用している場合は、ウェイ[ v - (n2 + 1)x2 ] も減算する必要があります。
ここで、少なくとも ( n1 + 1) $x1および ( n2 + 1) $x2が使用される構成を 2 回減算したため、ウェイを追加する必要があります[ v -(n1 + 1)x1 - (n2 + 1) x2 ] など
特に、
N = すべてのコインができるだけ多く使用される構成のセット、
Ai = 1 <= i <= mの場合、少なくともni + 1 個の$xiが使用される構成のセット
求めている結果 = | ん| - | A1 | - | A2 | .. - | 午前| + | A1とA2 | + | A1とA3 | + ... - | A1とA2とA3 | .....
無制限のコインで構成の数を計算するコードは、実際にはより単純です。
ways[0]=1;
for( int i = 0 ; i < count ; i++){
for( int j = coins[i] ; j < ways.size() ; j++ ){
ways[j] += ways[j-coins[i]];
}
}