<output id="qn6qe"></output>

    1. <output id="qn6qe"><tt id="qn6qe"></tt></output>
    2. <strike id="qn6qe"></strike>

      亚洲 日本 欧洲 欧美 视频,日韩中文字幕有码av,一本一道av中文字幕无码,国产线播放免费人成视频播放,人妻少妇偷人无码视频,日夜啪啪一区二区三区,国产尤物精品自在拍视频首页,久热这里只有精品12

      [雜記] 01背包記錄路徑

      [雜記] 01背包記錄路徑

      眾所周知,01背包的時間復雜度是\(O(nm)\)(n為物品數量,m為背包容量),空間復雜度是\(O(m)\)。如果還需要輸出最優解中的所有物品的話,時間復雜度不變,空間復雜度呢?

      你的第一反應可能是:我很快就可以給出一個空間復雜度也是\(O(m)\)的算法啊?

      但實際上這個算法是有問題的:

      int n;		// 物品數量
      int m;		// 背包容量
      int w[N];	// 物品重量
      int v[N];	// 物品價值
      int dp[M];	// dp數組
      int pre[M];	// 路徑
      
      void package01() {
          for (int i = 1; i <= n; i ++) {
              for (int j = m; j >= w[i]; j --) {
                  if (dp[j] < dp[j-w[i]] + v[i]) {
                      dp[j] = dp[j-w[i]] + v[i];
                      pre[j] = i;
                  }
              }
          }
      
          int j = m;
          while (pre[j] != 0) {
              int last = pre[j];
              printf("%d, ", last);
              j -= w[last];
          }
      }
      

      這樣寫有什么問題呢?

      當然有!

      比如對于下面的樣例:

      n = 3;
      m = 4;
      w[] = {1, 1, 2};
      v[] = {1, 1, 4};
      

      輸出結果就是

      3, 3,
      

      第三個物品被用了兩次。

      這時你可能恍然大悟,因為在第三個物品加入后,pre[2]被更新為了3,所以就丟失了前兩個物品的路徑。

      本質原因在于,一開始的01背包本來就是二維數組\(dp[i][j]\),表示“只使用前i個物品,背包容量為j時的最大價值”,這時\(pre[i][j]\)的意義就是“只使用前i個物品,背包容量為j,達到最大價值時最后一個購買的物品”。轉移是:

      if (dp[i-1][j] > dp[i-1][j-w[i]] + v[i]) {
      	dp[i][j] = dp[i-1][j-w[i]] + v[i];
      	pre[i][j] = i;
      }
      else {
      	dp[i][j] = dp[i-1][j];
      	pre[i][j] = pre[i-1][j];
      }
      

      路徑是:

      int i = n, j = m;
      while (pre[i][j] != 0) {
          int last = pre[i][j];
          printf("%d, ", last);
          i = last - 1; 
          j -= w[last];
      }
      

      如果把pre壓縮為1維,相當于最后只剩下\(pre[n][.]\),前面\(pre[<n][.]\)的路徑信息就丟失了,這樣就沒法輸出完整路徑了。

      那有沒有時間復雜度還是\(O(nm)\),空間復雜度低于\(O(nm)\)的做法呢?

      好吧我是沒想出來。

      不過倒是有一種能讓空間降低32倍的做法:將pre變成一個01數組,\(pre[i][j]=1\)表示“只使用前i個物品,背包容量為j,達到最大價值時最后一個購買的物品就是i”。這樣也能輸出完整的路徑。

      int i = n, j = m;
      while (i != 0) {
          while (!pre[i][j])
              i --;
          printf("%d, ", i);
          j -= w[i];
          i --;
      }
      

      如果有高人能給出空間復雜度低于\(O(nm)\)的做法,歡迎交流。

      posted @ 2022-12-06 14:28  CQzhangyu  閱讀(550)  評論(0)    收藏  舉報
      主站蜘蛛池模板: 亚洲国产精品色一区二区| 亚洲精品一区二区区别| 日本一区二区三区在线播放| 国产麻豆91网在线看| 亚洲深夜精品在线观看| 国产精品无码久久久久AV| 国产 另类 在线 欧美日韩| 18禁亚洲一区二区三区| 亚洲精品一区二区三区在| 四川少妇被弄到高潮| 亚洲免费最大黄页网站| 日本一高清二区视频久二区| 男人又大又硬又粗视频| 亚洲精品久久久久久无码色欲四季| 无码内射中文字幕岛国片| аⅴ天堂国产最新版在线中文| 重口SM一区二区三区视频| 久久精品中文字幕有码| 中文字幕第一页国产| 一区一区三区产品乱码| 欧洲亚洲精品免费二区| 亚洲自拍偷拍福利小视频| 亚洲a∨无码无在线观看| 国产女人在线视频| 99久久久无码国产精品免费| 午夜精品区| 日本边添边摸边做边爱喷水| 闻喜县| 久久国产精品老女人| 中文有无人妻VS无码人妻激烈| 久久88香港三级台湾三级播放| 人妻少妇精品中文字幕| 舒城县| 亚洲成av人最新无码不卡短片| 超碰伊人久久大香线蕉综合| 国产欧美va欧美va在线| 亚洲精品熟女一区二区| 巴彦淖尔市| 亚洲日本乱码熟妇色精品| 无码va在线观看| 97精品国产91久久久久久久|