アルゴリズム-01リュックサック問題【f[i][j]に対するjは超えない、ちょうど等しい、残りの空間の詳細】
3つの状況分析とコード解釈 j を超えないは に等しい余剰空間 タイトルは以下の通りです.
必要な入力:物品数n,最大容量v (n行)各物品の体積、質量 申請スペース: int n, v int vx[]各品目の体積 int m[]各品目の質量 int f[]]各状態における最大質量 まず、次の3つのケースを示します. f[i][j]は前のi個の物品を表す、体積がjを超えない前提での最大質量 である. f[i][j]は前のi個の物品を表す、体積がjにちょうど等しい前提での最大質量 である. f[i][j]は、前のi個の物品を表す、体積がjだけ残っていることを前提とした最大質量 である.
jを超えない
キーコード
一番大切なのはこれ f[i][j]:i番目のアイテムを選択しない場合の最大質量(if以前に付与されているため) . f[i-1][j-vx[i]:i番目のアイテムを選択しないときの最大質量であり、このときの体積はj-vx[i](ここで超えないのは、vx[i]を加えるとjを超えない) を満たすためである. f[i-1][j-vx[i]+w[i]がi番目のアイテムを選択する場合、体積がjを超えない最大質量 .
まだ理解していない人もいるかもしれませんが、例を挙げてみましょう.
解釈f[2][5-vx[3]+m[3]: f[2][5-vx[3]]:最初の2つのアイテムの中から選択され、体積が5-vx[3]を超えない場合の最大質量. f[2][5-vx[3]+m[3]:前の2つのアイテムの中から選択する、かつ体積が5-vx[3]を超えない場合の最大質量、その場合に第3のアイテムの質量を加える(このようにして得られるのは、前の3つのアイテムの選択下(この場合は第3のアイテムを選択した)体積が5を超えない最大質量) .
出力解答:f[n][v](maxを求める必要はありません)
超過しない詳細コードについて(1 D配列、2 D配列実装)
ちょうど等しい
この場合、その式は超えない場合と同じで、唯一異なるのは2つあります.判断違い:
解釈:j>=vx[i]:後ろの配列の境界を越えることを防止する
f[ i - 1 ][ j - vx[ i ] ] != 0:ゼロに等しい場合、証明前のi-1つの物品の中でj-vx[i]という体積の最大質量がない(0に等しくない場合、証明はj-vx[i]の体積の最大質量がある)
j==vx[i]:自分の体積がちょうどjであり、体積が0の最大質量が0である場合、このときは寄せられる出力が異なる: 状況にぴったり合う詳細コード(1次元配列、2次元配列実装)について
ざんりゅうくうかん
キーコード
なぜj+vx[i]なのかというと、i番目の商品を選んだ場合、このときの余剰体積は減少するに違いないので、iの体積を2と考え、例えば余剰体積を7と求めると、必ず余剰体積が9から変化してくる
f[ i ][ 7 ] = max(f[ i ][ 7 ],f[ i -1][ 7 + 2] + m[ i ]
したがって、余剰空間が7のときの最大質量は、余剰空間が9の最大質量にi番目の物品(その体積は2で、重量はm[i])を加えたものである.出力: 空き領域の詳細コード(1 D配列、2 D配列実装)について
ps:この3つのコードの実装はそれほど悪くありませんが、01リュックの問題を本当に理解するには、彼らを区別しなければなりません.これも自分が本当に理解しているかどうかを試すことでしょう.
N V 。 。
i vi, wi。
, , 。
。
,N,V, , 。
N , vi,wi, , i 。
, 。
0<N,V≤1000
0<vi,wi≤1000
4 5
1 2
2 4
3 4
4 5
:
8
必要な入力:
jを超えない
キーコード
for(int i = 1; i <= n; i++ ){// i
for(int j = 0; j <= v; j++ ){
f[i][j] = f[i - 1][j];// i
if(j >= vx[i])// j-vx[i] , v[i] , j
f[i][j] = max(f[i][j], f[i - 1][j - vx[i]] + m[i]);// j-vx[i], i ,
// f[i][j] : i , j ( f[i-1][j - vx[i] + m[i] )
}
}
一番大切なのはこれ
if(j >= vx[i])
f[i][j] = max(f[i][j], f[i - 1][j - vx[i]] + m[i]);
まだ理解していない人もいるかもしれませんが、例を挙げてみましょう.
f [3][5] = max(f[2][5], f[2][5-vx[3]] + m[3])
解釈f[2][5-vx[3]+m[3]:
出力解答:f[n][v](maxを求める必要はありません)
超過しない詳細コードについて(1 D配列、2 D配列実装)
ちょうど等しい
この場合、その式は超えない場合と同じで、唯一異なるのは2つあります.
for(int i = 1; i <= n; i++ ){// i , 2
for(int j = 0; j <= v; j++ ){//
f[i][j] = f[i - 1][j];// i
if(j >= vx[i] && (j == vx[i] || f[i - 1][j-vx[i]] != 0))
f[i][j] = max(f[i][j], f[i - 1][j - vx[i]] + m[i]);// j-vx[i], i ,
// i , i( j>=vx[i])
}
}
if(j >= vx[i] && (j == vx[i] || f[i - 1][j-vx[i]] != 0))
解釈:j>=vx[i]:後ろの配列の境界を越えることを防止する
f[ i - 1 ][ j - vx[ i ] ] != 0:ゼロに等しい場合、証明前のi-1つの物品の中でj-vx[i]という体積の最大質量がない(0に等しくない場合、証明はj-vx[i]の体積の最大質量がある)
j==vx[i]:自分の体積がちょうどjであり、体積が0の最大質量が0である場合、このときは寄せられる
f[ n ][0 ~ v] , 。
ざんりゅうくうかん
キーコード
for(int i = 1; i <= n; i++ ){// i
for(int j = 0; j <= v; j++ ){// j
f[i][j] = f[i - 1][j];// i
if(j + vx[i] <= v)//
f[i][j] = max(f[i][j], f[i - 1][j + vx[i]] + m[i]);// j+vx[i], i ,
// , i 2, 7 , 9
}
}
if(j + vx[i] <= v)//
f[i][j] = max(f[i][j], f[i - 1][j + vx[i]] + m[i]);
なぜj+vx[i]なのかというと、i番目の商品を選んだ場合、このときの余剰体積は減少するに違いないので、iの体積を2と考え、例えば余剰体積を7と求めると、必ず余剰体積が9から変化してくる
f[ i ][ 7 ] = max(f[ i ][ 7 ],f[ i -1][ 7 + 2] + m[ i ]
したがって、余剰空間が7のときの最大質量は、余剰空間が9の最大質量にi番目の物品(その体積は2で、重量はm[i])を加えたものである.
f[ n ][0 ~ v] , 。
ps:この3つのコードの実装はそれほど悪くありませんが、01リュックの問題を本当に理解するには、彼らを区別しなければなりません.これも自分が本当に理解しているかどうかを試すことでしょう.