01揹包問題 包含部分例題

2021-10-23 03:37:15 字數 1410 閱讀 4602

作為ds選手(資料結構也很菜) 最近開始回顧dp了 從最簡單的01揹包 開始  感覺dp比較鍛鍊思維  而我思維很爛

第一題是01揹包裸題  hdu 2602

01揹包  dp[i][j]表示 第i個物品 我們選出了體積為j的最大value 然後轉移一下就ok了

dp[i][j] = dp[i-1][j] 不選第i個

dp[i][j] = dp[i-1][j-vol[i]]+val[i] 選第i個  

#includeusing namespace std;

const int n = 1e3+10;

int dp[n][n],val[n],vol[n];

int main()

for(int i = 1; i <= n; i++)

for(int i = 1; i <= n; i++)

} printf("%d\n",dp[n][v]);

} return 0;

}

還可以把空間優化到o(n) 至於為啥j變成了逆序遍歷  大家畫一下 dp的狀態轉移圖就知道了

我們假設是正序的 j為j1的時候 進行了一次轉移 dp[j1] = dp[j1-vol[i]]+val[i]  我們選了i物品   假如j還小於v 我們繼續往上遍歷j   此時又進行了 一次轉移 記為j2 dp[j2] = dp[j2-vol[i]]+val[i]  不巧的是 j2-vol[i] = j1  那麼我們相當於在j1的狀態下又選了 i 物品 所以對於i物品我們會選多次  由此可見正序的錯誤性

反觀逆序的時候 就能保證每個物品只取一次  

#includeusing namespace std;

const int n = 1e3+10;

int dp[n],val[n],vol[n];

int main()

for(int i = 1; i <= n; i++)

for(int i = 1; i <= n; i++)

} printf("%d\n",dp[v]);

} return 0;

}

了解這個優化後我們可以直接來看 洛谷 p1616 瘋狂的採藥 完全揹包裸題

另乙個題 ch 5201 稍微變形一下的01揹包 也很裸

#includeusing namespace std;

int n,m;

int dp[100050];

int a[103];

int main()

} printf("%d\n",dp[m]);

return 0;

}

0 1揹包與部分揹包

0 1揹包 問題描述 有n件物品和乙個容量為v的揹包。第i件物品的費用是c i 價值是w i 求解將哪些物品裝入揹包可使價值總和最大。所謂0 1揹包,表示每乙個物品只有乙個,要麼裝入,要麼不裝入。解決方案 考慮使用動態規劃 dynamic programming 問題求解 假定ak是放入的最後乙個物...

01揹包與部分揹包

有n件物品和乙個容量為c的揹包,第i件物品的費用是w i 價值是v i 求在不超過揹包的最大容量下,求能得到最大的價值 dp i j 表示前i件物品放入乙個容量為j的揹包可以獲得的最大價值 考慮第i件物品 放與不放 那麼就有兩種狀態。如果不放,那麼當前價值dp i j dp i 1 j 1 也就是和...

演算法導論 0 1揹包問題 與 部分揹包

0 1揹包 問題描述 n件物品,第i件物品價值 v i 元,重w i 磅。希望用 w磅的書包 拿走總價值最貴的物品。物品不可以分割故稱為0 1揹包 部分揹包 問題描述 n件物品,第i件物品價值 vi 元,重wi 磅。希望用 w磅的揹包 拿走最重的物品。第i件物品可以都拿走,也可以拿走一部分。物品可以...