• uvalive4327(单调队列优化)


    这题我有闪过是用单调队列优化的想法,也想过有左右两边各烧一遍。 但是不敢确定,搜了题解,发现真的是用单调队列,然后写了好久,调了好久下标应该怎么变化才过的。

    dp[i][j] 表示走到第i行,第j个竖线的最大价值。

    dp[i][j] = max(dp[i-1][k]+pre[i][j-1]-pre[i][k-1]);  从左往右

    dp[i][j] = max(dp[i][j],dp[i-1][k]+suf[i][j]-suf[i][k]); 从右往左

     1 #pragma warning(disable:4996)
     2 #pragma comment(linker, "/STACK:1024000000,1024000000")
     3 #include <stdio.h>
     4 #include <string.h>
     5 #include <time.h>
     6 #include <math.h>
     7 #include <map>
     8 #include <set>
     9 #include <queue>
    10 #include <stack>
    11 #include <vector>
    12 #include <bitset>
    13 #include <algorithm>
    14 #include <iostream>
    15 #include <string>
    16 #include <functional>
    17 const int INF = 1 << 30;
    18 typedef __int64 LL;
    19 /*
    20 dp[i][j]表示走到第i个横线,第j个竖线的最大值
    21 dp[i][j] = max(dp[i-1][k] + sum[j-1] - sum[k-1])
    22 单调队列优化维护队首最大值,
    23 */
    24 
    25 int q[11111], head, tail;
    26 int dp[111][11111];
    27 int a[111][11111];
    28 int b[111][11111];
    29 int pre[111][11111], suf[111][11111];
    30 int sum1[111][11111];
    31 int sum2[111][11111];
    32 int main()
    33 {
    34     int n, m, k;
    35 
    36     while (scanf("%d%d%d", &n, &m, &k),n+m+k)
    37     {
    38         memset(dp, 0, sizeof(dp));
    39         memset(pre, 0, sizeof(pre));
    40         memset(suf, 0, sizeof(suf));
    41         memset(sum1, 0, sizeof(sum1));
    42         memset(sum2, 0, sizeof(sum2));
    43         n++;
    44         for (int i = 1;i <= n;++i)
    45         {
    46             for (int j = 1;j <= m;++j)
    47             {
    48                 scanf("%d", &a[i][j]);
    49                 pre[i][j] = pre[i][j - 1] + a[i][j];
    50                 suf[i][j] = a[i][j];
    51             }
    52             for (int j = m;j >= 1;--j)
    53                 suf[i][j] += suf[i][j + 1];
    54 
    55         }
    56         for (int i = 1;i <= n;++i)
    57         {
    58             for (int j = 1;j <= m;++j)
    59             {
    60                 scanf("%d", &b[i][j]);
    61                 sum1[i][j] = b[i][j];
    62                 sum2[i][j] = sum2[i][j - 1] + b[i][j];
    63             }
    64             for (int j = m;j >= 1;--j)
    65                 sum1[i][j] += sum1[i][j + 1];
    66         }
    67         for (int i = n;i >= 1;--i)
    68         {
    69             head = tail = 0;
    70             for (int j = 1;j <= m + 1;++j)
    71             {
    72                 while (head < tail && dp[i + 1][j] - pre[i][j - 1] >= dp[i + 1][q[tail - 1]] - pre[i][q[tail - 1] - 1])
    73                     tail--;
    74                 q[tail++] = j;
    75                 while (head<tail && sum2[i][j-1] - sum2[i][q[head]-1]>k)
    76                     head++;
    77                 dp[i][j] = dp[i + 1][q[head]] + pre[i][j - 1] - pre[i][q[head]-1];
    78             }
    79             head = tail = 0;
    80             
    81             for (int j = m+1;j >= 1;--j)
    82             {
    83                 while (head < tail&&dp[i + 1][j] - suf[i][j ] >= dp[i + 1][q[tail - 1]] - suf[i][q[tail - 1] ])
    84                     tail--;
    85                 q[tail++] = j;
    86                 while (head<tail&&sum1[i][j] - sum1[i][q[head]]>k)
    87                     head++;
    88                 dp[i][j] =std::max(dp[i][j], dp[i + 1][q[head]] + suf[i][j] - suf[i][q[head]]);
    89             }
    90         }
    91         int ans = 0;
    92         for (int j = 1;j <= m + 1;++j)
    93             ans = std::max(ans, dp[1][j]);
    94         printf("%d
    ", ans);
    95     }
    96     return 0;
    97 }
    View Code
  • 相关阅读:
    安卓天天练练(三)常用组件Toast
    安卓天天练练(二)相对布局和帧布局
    javascript表单操作
    JavaScript replace() 方法
    android基础(一)
    四大类NoSQL数据库
    php基础八(cookie)
    php基础(七)文件
    php基础(六)Include
    php基础(五)日期
  • 原文地址:https://www.cnblogs.com/justPassBy/p/4774224.html
Copyright © 2020-2023  润新知