8.4集訓
上午
考試
下午
講dp!!!
我們來通過通過幾道例題來體會一下什麼是dp
01揹包
將n件有著各自體積和價值的物品裝入一個容積為m的揹包中,求最大的總價值
狀態:\(f[i][j]\)表示前\(i\)件物品放入揹包為\(j\)的揹包中所能獲得的最大總價值
轉移:\(f[i][j] = max(f[i-1][j], f[i-1][j-v[i]]+w[i])\)
結果:\(f[n][m]\)
最長不下降子序列
給出一個長度為n 的序列,求最長的子序列,滿足這些元素依次不減
狀態:設\(f[i]\)表示以\(i\)為結尾的最長不下降子序列的最長長度
轉移:\(f[i] = max(f[j]+1)\)
結果:\(max(f[i])\)
上面是\(O(n^2)\)做法,還有一種\(O(nlogn)\)的做法:
狀態:設\(f[i]\)表示長度為\(i\)的的最長不下降子序列的最後一個元素的最小值
舉個例子:
有序列\(a[] = {8,2,3,5,7,6,4}\),所以可得:
\(f[0] = 0,f[1] = 2, f[2] = 3, f[3]=5,f[4]=7\)(第一遍掃)
遇到\(6\)考慮更新\(f[4]\),遇到\(4\)考慮更新\(f[3]\)
至於為什麼是logn的,因為每次是二分查詢(\(lower\)_\(bound\)是log的)
再次考慮\(dp\)
要把式子推出來再去寫程式碼
下面有幾道一般dp,沒什麼特點,就是難
渡河問題
狀態:\(f[i]\)表示將前\(i\)頭牛運到對岸的時間
轉移:\(f[i] = min(f[j]+2*M+sum[i-j])\)其中\(sum\)為字首和
結果:\(f[n]\)
解題
給出貪心的\(Hack\)資料:
50 5
40 10
10 40
10 5
10 3
10 2
狀態:\(f[i][j]\)表示處理\(1\)到\(j\)的題,最後一次選擇了\(i\)到\(j\)的最短月數
轉移:\(f[i][j] = min(f[k][i-1]+1/2)\)
結果:\(min(f[i][p])+1\)