日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

POJ 1821 Fence ★(单调队列优化DP)

發布時間:2025/4/5 编程问答 37 豆豆
生活随笔 收集整理的這篇文章主要介紹了 POJ 1821 Fence ★(单调队列优化DP) 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
題目大意:有一道線性籬笆由N個連續的木板組成。有K個工人,你要叫他們給木板涂色。每個工人有3個參數:L 表示 這個工人可以涂的最大木板數目,S表示這個工人站在哪一塊木板,P表示這個工人每涂一個木板可以得到的錢。要注意的是,工人i可以選擇不涂任何木板,否則,他的涂色區域必須是連續的一段,并且S[i]必須包含在內。 最后還有,每塊木板只能被涂一次。 ? 狀態方程比較容易想:dp[i][j]表示第i個人刷的最后一面墻是j時的最大獲利,則 dp[i][j]=max(dp[i-1][k]+(j-k)*p[i]) j-l[i]+1<=k+1<=s[i] ? ? ? ? (*) dp[i][j]=max(dp[i-1][j],dp[i][j-1],dp[i][j])//第i個人不刷,第j面墻不刷 ? 但是O(k*n^2)的復雜度顯然不能接受。而針對(*)這種“特殊”的轉移方程,我們可以用單調隊列把它優化到O(1): dp[i][j]=max(dp[i-1][k]-k*p[i])+j*p[i] 其中j*p[i]在i,j兩重循環中相當于常數,所以,對于狀態dp[i][j]只要單調隊列維護dp[i-1][k]-k*p[i]的最大值即可 ? 單調隊列維護過程(可以回過頭看看POJ 2823---單調隊列的模型): 單調隊列具體的做法是:最外層循環為i,首先把j=1~s[i]-1轉移完(因為它不涉及第三個轉移),然后把(j-l[i]<=k<=s[i]-1)的決策點的F[i-1,k]-p[i]*k依次入隊建立“入隊早晚時間遞增,F[i-1,k]-p[i]*k的值遞減”的單調隊列,接下來循環j=s[i]~s[i]+l[i]-1,進行這三個轉移(第三個轉移只需要用隊首元素),其中每次需要把隊首超出長度限制的決策點出隊;最后把剩下的到n循環完,只需要前兩個轉移。 ? #include #include #include #include #include #include #include #include #include #include #include #include #define MID(x,y) ((x+y)>>1) using namespace std; typedef long long LL; struct worker{int l, p, s; }w[105]; bool cmp(worker a, worker b){return a.s < b.s; } int f[105][16005]; int n,k; void debug(){for (int i = 0; i <= k; i ++){for (int j = 0; j <= n; j ++)printf("%d %d %d\n", i, j, f[i][j]);} } deque Q; void initQ(){while(!Q.empty())Q.pop_back(); } int main(){scanf("%d %d", &n, &k);for (int i = 1; i <= k; i ++)scanf("%d %d %d", &w[i].l, &w[i].p, &w[i].s);sort(w+1, w+k+1, cmp); //別忘了先按S排序!for (int i = 1; i <= k; i ++){for (int j = 0; j < w[i].s; j ++)f[i][j] = max(f[i-1][j], f[i][j-1]);//單調隊列initQ();for (int j = max(0, w[i].s - w[i].l); j < w[i].s; j ++){while(!Q.empty() && f[i-1][Q.back()] - Q.back()*w[i].p <= f[i-1][j] - j*w[i].p)Q.pop_back();Q.push_back(j);}for (int j = w[i].s; j < min(w[i].s + w[i].l, n+1); j ++){while (!Q.empty() && Q.front() < j - w[i].l)Q.pop_front();f[i][j] = max(f[i-1][j], f[i][j-1]);f[i][j] = max(f[i][j], f[i-1][Q.front()] - Q.front()*w[i].p + j * w[i].p); // 樸素DP: // for (int p = max(0, j - w[i].l); p <= j; p ++) // f[i][j] = max(f[i][j], f[i-1][p] + (j - p)*w[i].p);}for (int j = w[i].s + w[i].l; j <=n; j ++)f[i][j] = max(f[i-1][j], f[i][j-1]);}debug();int res = 0;for (int j = 1; j <= n; j ++)res = max(res, f[k][j]);printf("%d\n", res);return 0; } ?

轉載于:https://www.cnblogs.com/AbandonZHANG/archive/2013/02/21/4114223.html

總結

以上是生活随笔為你收集整理的POJ 1821 Fence ★(单调队列优化DP)的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。