fork(4) download
  1. // 0-1ナップサック問題
  2. // 重さと価値がそれぞれ、wi,viであるようなn個の品物があります。
  3. // これらの品物から、重さの総和がWを超えないように選んだ時の
  4. // 価値の総和の最大値を求めなさい。
  5.  
  6.  
  7. #include <stdio.h>
  8. #include <iostream>
  9. #include <algorithm>
  10.  
  11. using namespace std;
  12.  
  13. // 入力値の上限
  14. const int MAX_N = 100; // 品物数の上限
  15. const int MAX_W = 10000; // 重さの上限の上限
  16.  
  17. // 入力値
  18. int N; // 品物の数
  19. int W; // 重さの上限(制約条件)
  20. int Weight[MAX_N]; // 品物nの重さ
  21. int Value[MAX_N]; // 品物nの価値
  22.  
  23.  
  24. //---------- 枝刈り探索 ----------
  25. int MaxValueEdakari; // 価値の最大
  26. void dfsEdakari(int n, int totalWeight, int totalValue)
  27. {
  28. // 枝刈り。重さが上限をすでに超えたときは打ち切り
  29. if(totalWeight>W)
  30. {
  31. return;
  32. }
  33.  
  34. // 他にも、残り全部の品物をとったとしても、価値の最大を更新できないとき、ここで枝刈りができる。
  35.  
  36. if(n==N)
  37. {
  38. // 全部の品物を見たので、最大価値の更新
  39. MaxValueEdakari = max(MaxValueEdakari,totalValue);
  40. return;
  41. }
  42.  
  43. dfsEdakari(n+1, totalWeight+Weight[n], totalValue+Value[n]); // 品物nを取る
  44. dfsEdakari(n+1, totalWeight, totalValue); // 品物nを取らない
  45. }
  46.  
  47. //---------- メモ化再帰 ----------
  48. int dp[MAX_N][MAX_W]; // dp[n][totalWeight=品物n~N-1番目の合計の重さ]=品物n~N-1番目の価値合計の最大値
  49. int dfsMemo(int n, int totalWeight)
  50. {
  51. if(n==N)
  52. {
  53. // 品物を1つも選んでないので、価値は0
  54. return 0;
  55. }
  56.  
  57. int& memo = dp[n][totalWeight]; // 関数の入力値n,totalWeightを、そのまま配列のindexに使うのがポイント
  58.  
  59. if(memo>=0)
  60. {
  61. // すでに関数の出力は一度計算してメモ化されてるので、即return;
  62. return memo;
  63. }
  64.  
  65. // メモ化する
  66. memo=0;
  67.  
  68. // 取る
  69. if(totalWeight+Weight[n]<=W) // 重さ上限チェック
  70. {
  71. memo = max(memo,dfsMemo(n+1, totalWeight+Weight[n])+Value[n]);
  72. }
  73.  
  74. // 取らない
  75. memo = max(memo,dfsMemo(n+1, totalWeight));
  76.  
  77. return memo;
  78. }
  79.  
  80.  
  81. int main()
  82. {
  83. // 入力
  84. cin >> N >> W;
  85. for (int n = 0; n < N; n++)
  86. {
  87. cin >> Weight[n] >> Value[n];
  88. }
  89.  
  90. //---------- 枝刈り探索 ----------
  91. MaxValueEdakari = -1;
  92. dfsEdakari(0,0,0);
  93.  
  94. //---------- メモ化再帰 ----------
  95. for (int n = 0; n < MAX_N; n++)
  96. {
  97. for (int w = 0; w < MAX_W; w++)
  98. {
  99. dp[n][w]=-1;
  100. }
  101. }
  102. const int MaxValueMemo = dfsMemo(0,0);
  103.  
  104. // 出力
  105. cout << " MaxValueEdakari=" << MaxValueEdakari << " MaxValueMemo=" << MaxValueMemo << endl;
  106.  
  107. return 0;
  108. }
  109.  
Success #stdin #stdout 0s 7248KB
stdin
5
100
78 25
16 90
30 29
40 80
5 18 
stdout
 MaxValueEdakari=217 MaxValueMemo=217