• HDU 4374 One hundred layer [单调队列优化DP]


      N层楼,每层M个有分数的格子,一开始在第一层的S点,每层最多不能连续走T个就必须下楼,求到达最底层能获得的最大分数。

      经典的单调队列优化问题,用A[i][j]表示前缀和,now表示当前层,pre表示上一层,可以得到以下递推式:

      当前层从左向右走,d[now][i]=max(d[pre][j]+A[now][i]-A[now][j-1]) = max((d[pre][j]-A[now][j-1])+A[now][i]) (j<=i)

      当前层从右向左走,d[now][i]=max(d[pre][j]+A[now][j]-A[now][i-1]) = max((d[pre][j]+A[now][j])-A[now][i-1]) (j>i)

      括号中的项为单调队列中的比较值,然后d[now][i]取从左和从右走的最大值即可。

      

     1 #include <stdio.h>
     2 #include <string.h>
     3 #include <math.h>
     4 #include <algorithm>
     5 #define INF 0x3f3f3f3f
     6 using namespace std;
     7 int n, m, x, tt;
     8 int mz[105][10005];
     9 int d[10005], t[10005];
    10 int q[10005], front, rear;
    11 int main(){
    12     //freopen("test.in","r",stdin);
    13     while (scanf("%d%d%d%d", &n, &m, &x, &tt) != EOF) {
    14         for (int i = 1; i <= n; i++)
    15             for (int j = 1; j <= m; j++)
    16                 scanf("%d", &mz[i][j]), mz[i][j] += mz[i][j-1];
    17         for (int i = 1; i <= m; i++) {
    18             if (abs(i-x) > tt) d[i] = -INF;
    19             else d[i] = x>i ? mz[1][x] - mz[1][i-1] : mz[1][i] - mz[1][x-1];
    20         }
    21         for (int i = 2; i <= n; i++) {
    22             front = rear = 0;
    23             for (int j = 1; j <= m; j++) t[j] = d[j] + mz[i][j] - mz[i][j-1];
    24             for (int j = 1; j <= m; j++) {
    25                 while (front < rear && j - q[front] > tt) front++;
    26                 if (front < rear) t[j] = max(t[j], d[q[front]] + mz[i][j] - mz[i][q[front]-1]);
    27                 while (front < rear && d[q[rear-1]] - mz[i][q[rear-1]-1] < d[j] - mz[i][j-1]) --rear;
    28                 q[rear++] = j;
    29             }
    30             front = rear = 0;
    31             for (int j = m; j >= 1; j--) {
    32                 while (front < rear && q[front] - j > tt) front++;
    33                 if (front < rear) t[j] = max(t[j], d[q[front]] + mz[i][q[front]] - mz[i][j-1]);
    34                 while (front <rear && d[q[rear-1]] + mz[i][q[rear-1]]< d[j] + mz[i][j]) --rear;
    35                 q[rear++] = j;
    36             }
    37             for (int j = 1; j <= m; j++) d[j] = t[j];
    38         }
    39         int ans = 0;
    40         for (int i = 1; i <= m; i++) ans = max(ans, d[i]);
    41         printf("%d\n", ans);
    42     }
    43     return 0;
    44 }
  • 相关阅读:
    AirtestProject2airtest安装与连接模拟器 广深
    人生苦短我学Java11常用类及方法 广深
    linux4更改系统时间时区为Shanghai 广深
    人生苦短我学Java12异常处理/集合/ArrayList与LinkedList/队列/堆栈/链表 广深
    人生苦短我学Java14HashSet/Map等实现类 广深
    Windows后台运行python等程序/开机自启程序 广深
    AirtestProject1airtest框架简介 广深
    人生苦短我学Java13泛型/Set集合/二叉树 广深
    jenkins5使用http请求远程构建Job 广深
    ThinkPHP distinct count 统计查询写法
  • 原文地址:https://www.cnblogs.com/swm8023/p/2717883.html
Copyright © 2020-2023  润新知