zoukankan      html  css  js  c++  java
  • LA 4327 多段图

    题目链接:https://vjudge.net/contest/164840#problem/B

    题意:

    从南往北走,横向的时间不能超过 c;

    横向路上有权值,求权值最大;

    分析:

    n<=100,m<=10000

    数据范围很大了,基本上要n*m;

    分析每个交叉路口,每个交叉路口,可以从下一行的左边,或者下一行的右边过来;

    那么这个交叉路口就是max(L[j],R[j]);

    怎么得到,某一个交叉路口从左边来,可以有哪些点呢? 不可能循环跑一遍(m的范围);

    就用了一个Q双端队列来维护;

    怎么得到,从哪个点上来最优呢? 在这个队列中的点也不能循环跑一遍;

    还是利用这个队列;维护他这个队列是单调队列就好了,

     1 #include <bits/stdc++.h>
     2 
     3 using namespace std;
     4 
     5 #define LL long long
     6 
     7 const int maxn = 105;
     8 const int maxm = 10100;
     9 LL f[maxn][maxm],t[maxn][maxm],L[maxm],R[maxm],n,m,c,d[maxn][maxm];
    10 
    11 deque<int> Q;
    12 int Lfunc(int j,int i) {
    13     return d[i-1][j] - f[i][j];
    14 }
    15 
    16 int Rfunc(int j,int i) {
    17     return d[i-1][j] + f[i][j];
    18 }
    19 
    20 int main() {
    21     while(scanf("%lld %lld %lld",&n,&m,&c)==3&&n) {
    22         for(int i=1; i<=n+1; i++)
    23             for(int j=0; j<=m; j++) {
    24                 if(!j) f[i][j] = 0;
    25                 else {
    26                     scanf("%lld",&f[i][j]);
    27                     f[i][j]+=f[i][j-1];
    28                 }
    29             }
    30 
    31 
    32         for(int i=1; i<=n+1; i++)
    33             for(int j=1; j<=m; j++) {
    34                 if(!j) t[i][j] = 0;
    35                 else {
    36                     scanf("%lld",&t[i][j]);
    37                     t[i][j]+=t[i][j-1];
    38                 }
    39             }
    40 
    41 
    42         for(int i=0; i<=m; i++)
    43             d[0][i] = 0;
    44 
    45         for(int i=1; i<=n+1; i++) {
    46             L[0] = d[i-1][0];
    47             Q.clear();
    48             Q.push_back(0);
    49             for(int j=1; j<=m; j++) {
    50                 while(!Q.empty()&&t[i][j]-t[i][Q.front()]>c) {
    51                     Q.pop_front();
    52                 }
    53                 L[j] = d[i-1][j];   //从左到达 j 的最优值
    54                 if(!Q.empty()) L[j] =max(L[j],Lfunc(Q.front(),i)+f[i][j]);
    55                 while(!Q.empty()&&Lfunc(Q.back(),i)<=Lfunc(j,i)) Q.pop_back();
    56                 Q.push_back(j);
    57             }
    58             
    59             
    60             R[0] = d[i-1][m];
    61             Q.clear();
    62             Q.push_back(m);
    63             for(int j=m-1; j>=0; j--) {
    64                 while(!Q.empty()&&t[i][Q.front()]-t[i][j]>c) Q.pop_front();
    65                 R[j] = d[i-1][j];
    66                 if(!Q.empty()) R[j] = Rfunc(Q.front(),i)-f[i][j];
    67                 while(!Q.empty()&&Rfunc(Q.back(),i)<=Rfunc(j,i)) Q.pop_back();
    68                 Q.push_back(j);
    69             }
    70             for(int j=0; j<=m; j++)
    71                 d[i][j] = max(L[j],R[j]);
    72         }
    73         
    74         LL res;
    75         for(int i=0; i<=m; i++) {
    76             if(!i) res=d[n+1][i];
    77             else res = max(d[n+1][i],res);
    78         }
    79         printf("%lld
    ",res);
    80     }
    81     return 0;
    82 }
    View Code
  • 相关阅读:
    小小c#算法题
    .net中值类型、引用类型理解的c#代码示例
    小小c#算法题
    小小c#算法题
    小小c#算法题
    小小c#算法题
    python 正则表达式(一)
    python string 文本常量和模版
    centos6安装redis
    sqoop命令总结
  • 原文地址:https://www.cnblogs.com/TreeDream/p/6896581.html
Copyright © 2011-2022 走看看