作為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件物品可以都拿走,也可以拿走一部分。物品可以...