アルゴリズム-01リュックサック問題【f[i][j]に対するjは超えない、ちょうど等しい、残りの空間の詳細】


3つの状況分析とコード解釈
  • j
  • を超えない
  • に等しい
  • 余剰空間
  • タイトルは以下の通りです.
      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 58
    

    必要な入力:
  • 物品数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を超えない
    キーコード
    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[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 [3][5] = max(f[2][5], f[2][5-vx[3]] + m[3])
    

    解釈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つあります.
    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]      ,                 。
    
  • 状況にぴったり合う詳細コード(1次元配列、2次元配列実装)について
    ざんりゅうくうかん
    キーコード
    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]      ,                 。
    
  • 空き領域の詳細コード(1 D配列、2 D配列実装)について
    ps:この3つのコードの実装はそれほど悪くありませんが、01リュックの問題を本当に理解するには、彼らを区別しなければなりません.これも自分が本当に理解しているかどうかを試すことでしょう.