演算法:uva-1427 Parade (單調隊列最佳化dp)

來源:互聯網
上載者:User

題意

F城由n+1個橫向路和m+1個豎向路組成。你的任務是從最南邊的路走到最北邊的路,使得走過 的路上的高興值和最大(注意,一段路上的高興值可以是負數)。同一段路不能經過兩次,且不能從北往南 走。另外,在每條橫向路上所花的時間不能超過k。

思路

這題在uva和LA上又是不能評測, 於 是在hdu和poj上評測了這題

這題狀態比較容易想到, f(i, j)表示走到第i行第j點的最大價值

對於 每一點,可以從下一行的走上來,也可以從左邊走過來,也可以從右邊走過來

設L(i, j)表示第i行從左邊 走到j點的最大價值,R(i, j)表示第i行從右邊走過來的最大價值

可以得到, f(i, j) = max{ L(i,j), R (i, j), f(i+1, j) }

關鍵是要求L(i, j)和R(i, j)

sum(i, j)表示第i行的前j個路段價值之和

L(i, j) = max{ f(i+1, k) + sum(i, j) - sum(i, k) | 1<=k<=j && k走到j的總時間 <= k}

轉換可以變成:

L(i, j) = max{ f(i+1, k) - sum(i, k)| 1<=k<=j && k走 到j的總時間 <= k}  + sum(i, j)

所以只要維護一個k,使得f(i+1, k) - sum(i, k)的值最 大,這可以用單調隊列來維護這個值

求R(i, j)的方法也可L一樣

代碼

/**==========================================* This is a solution for ACM/ICPC problem** @source:uva-1427 Parade* @author: shuangde* @blog: blog.csdn.net/shuangde800* @email: zengshuangde@gmail.com*===========================================*/#include <iostream>#include <cstdio>#include <algorithm>#include <vector>#include <queue>#include <cmath>#include <cstring>#define MP make_pairusing namespace std;    typedef pair<int, int >PII;typedef long long int64;const int INF = 0x3f3f3f3f;const double PI = acos(-1.0);const int MAXN = 10005;    int n, m, k;int mat[105][MAXN];int t[105][MAXN];int f[105][MAXN];int l[MAXN], r[MAXN];int sumVal[MAXN], sumT[MAXN];        inline int getSum(int* sum, int i, int j) {return sum[i] - sum[j];}    // 讀入加速inline int nextInt(){char c = getchar();while(!isdigit(c) && c!='-') c = getchar();int sigma = 1;if(c=='-') {sigma = -1;c = getchar();}int x = 0;while(isdigit(c)){x = x*10+c-'0';c=getchar();}return x*sigma;}    int main(){    while (~scanf("%d%d%d", &n, &m, &k) && n+m+k) {        for (int i = 1; i <= n + 1; ++i)for (int j = 2; j <= m + 1; ++j)mat[i][j] = nextInt();    for (int i = 1; i <= n + 1; ++i)for (int j = 2; j <= m + 1; ++j)t[i][j] = nextInt();    // initmemset(f[n+2], 0, sizeof(f[n+2]));    for (int i = n + 1; i >= 1; --i) {deque<int>que;// from left to rightsumVal[0] = sumT[0] = 1;int front = 0, rear = 0;for (int j = 1; j <= m + 1; ++j) {sumVal[j] = sumVal[j-1] + mat[i][j];sumT[j] = sumT[j-1] + t[i][j];    int tmp = f[i+1][j] - sumVal[j];while(!que.empty() && f[i+1][que.back()]-sumVal[que.back()] <= tmp)que.pop_back();que.push_back(j);while (!que.empty() && getSum(sumT, j, que.front()) > k)que.pop_front();    if (i < n + 1)l[j] = max(f[i+1][j], f[i+1][que.front()] - sumVal[que.front()] + sumVal[j]);elsel[j] = max(-INF, sumVal[j] - sumVal[que.front()]);    }    // clearwhile (!que.empty()) que.pop_back();    // from right to left// http://www.bianceng.cnsumVal[m+2] = sumT[m+2] = 0;for (int j = m + 2; j >= 2; --j) {sumVal[j] = sumVal[j+1] + mat[i][j];sumT[j] = sumT[j+1] + t[i][j];    int tmp = f[i+1][j-1] - sumVal[j];    while (!que.empty() && f[i+1][que.back()-1]-sumVal[que.back()] <= tmp)que.pop_back();que.push_back(j);while (!que.empty() && getSum(sumT, j, que.front()) > k)que.pop_front();    if (i < n + 1)r[j] = max(f[i+1][j-1], f[i+1][que.front()-1] - sumVal[que.front()] + sumVal[j] );elser[j] = max(-INF, sumVal[j]- sumVal[que.front()]);///////////////////////////f[i][j-1] = max(l[j-1], r[j]);}}int ans = 0;for (int i = 1; i <= m +1; ++i)ans = max(ans, f[1][i]);printf("%dn", ans);}    return 0;}

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.