zoukankan      html  css  js  c++  java
  • 单调队列优化dp

    洛谷p3800(单调队列优化DP

    题目背景

    据说在红雾异变时,博丽灵梦单身前往红魔馆,用十分强硬的手段将事件解决了。

    然而当时灵梦在Power达到MAX之前,不具有上线收点的能力,所以她想要知道她能收集多少P点,然而这个问题她答不上来,于是她找到了学OI的你。

    题目描述

    可以把游戏界面理解成一个NM列的棋盘,有K个格子上有P点,其价值为val(i,j)

    初始灵梦可以选择在第一行的任意一个格子出发,每秒她必须下移一格。

    灵梦具有一个左右移动的速度T,可以使她每秒向左或右移动至多T,也可以不移动,并且不能折返。移动可视为瞬间完成,不经过路途上的点,只能获得目标格子的P点。

    求最终她能获得的POWER值最大是多少?

    输入输出格式

    输入格式:

    第一行四个数字,N,M,K,T

    接下来K行每行3个数字x,y,v,代表第x行第y列有一个valvP点,数据保证一个格子上最多只有1P点。

    输出格式:

    一个数字

    输入输出样例

    输入样例#1 复制

    3 3 4 1

    1 1 3

    1 2 1

    2 2 3

    3 3 3

    输出样例#1 复制

    9

    说明

    对于40%的测试点,1<=N,M,T,K<=200

    对于100%的测试点,1<=N,M,T,K<=4000

    v<=100N,M,K,T均为整数

    题解:

    看完题目,可发现这个题目像数塔,但是因为有速度,在一行可以左右移,所以可推出状态转移方程f[i,j]=max{f[i,j-k]~f[i,j+k],},所以复杂度为i*j*k,看范围,会超时。再观察题目,发现对于每个上一行,在一个区间内找一个最大值,且一格一格移动,联想到‘扫描’,可以用单调队列优化。先处理出k范围的队列(里面毕竟要先有数吧)(预处理)之后才能进行删头处理。再对第i行每个状态进行处理(1~j)可用滚动数组。此处单调队列与导弹拦截的优化不同,这是一个一个移的

    var
     m1,s,n,m,i,k,j,tt,x,y,z,t,h,max,l:longint;
     ans:int64;
     q,f,dp,id:array[-10..100000]of longint;//q队列,id下标数组,dp滚动数组(协助存上一层数),f答案数组
     a:array[-1..4000,-1..4000]of longint;
    begin
     readln(n,m,s,L);
      for i:=1 to s do
       begin
         readln(x,y,z);
         a[x,y]:=z;
       end;
    
       for i:=1 to m do  f[i]:=a[1,i];
    
        for i:=2 to n do
         begin
         h:=1;t:=1; q[1]:=f[1];id[1]:=1;
          for j:=2 to l do
          begin
    
                 while (f[j]>q[t])and(h<=t)do dec(t);
                      inc(t); q[t]:=f[j];id[t]:=j;
    
          end;
           k:=l;//dp[1]=q[h]+a[1,i];
           for j:=1 to m do //you wrong here这里我调了好久,本来以为1已经计算过了,但不知道为什么没有,2改成1 就过了,所以dp尽量用记忆化
            begin
             if k+1<=m then
              begin
                inc(k);
                while (q[t]<f[k])and(h<=t) do dec(t);
                inc(t); q[t]:=f[k];id[t]:=k;
              end;
                 begin  while id[h]<j-l do inc(h);
                       dp[j]:=q[h]+a[i,j];
                 end;
            end;
         for j:=1 to m do
          begin
            f[j]:=dp[j];
            if max<f[j] then max:=f[j];
          end;
        end;
    
         writeln(max);
    end.
    NOIP2018 rp++
  • 相关阅读:
    Maven的settings.xml配置详解
    Activiti创建表(三)
    解决报错:The server time zone value 'Öйú±ê׼ʱ¼ä' is unrecognized
    解决报错(Could not create connection to database server.)
    Activiti插件安装(二)
    2018年四川理工学院软件工程考试大纲(软件工程概述)
    通过myclipse建立一个简单的Hibernate项目(PS:在单元测试中实现数据的向表的插入)
    MySQL如何永久解决由dos编码格式导致MySQ的显示乱码
    nyoj 209 + poj 2492 A Bug's Life (并查集)
    nyoj 208 + poj 1456 Supermarket (贪心)
  • 原文地址:https://www.cnblogs.com/brilliant107/p/9471173.html
Copyright © 2011-2022 走看看