看完题面想了一会发现只会写$n^3$,愣了一会才想出了单调队列优化的做法。

90分算法:

设$f_{i, j, k}$表示第$i$分钟在第$j$座城市已经走了$k$步的最大价值,转移显然,时间复杂度$O(n^3)$。

但是我没有实现它。

100分算法:

思考一下最终的答案是怎样选出来的,我们把矩阵画出来:

发现题目可以转化为在这个矩阵上选若干个斜对角线,使得每一列都有且仅有一个被选到,最后获得的总价值为所有选到的格子上的值再减去所有斜对角线开始的格子对应的代价,使这个总价值最大。

设$f_{i, j}$表示到第$i$分钟,当前再$j$能选到的最大价值,那么发现最多只能从$1-p$层上转移过来。

$f_{i, j} = max(max(f_{i - k,o}) + calc(i- k, i) - cost_{pos(j, k)}) (1 \leq k \leq p - 1) (1 \leq o \leq n)$

$calc(i, j)$表示这一条对角线(从$i$层到$j$层)上的价值总和,可以通过斜线上预处理前缀和得到,$pos(i, j)$表示$i$上移$j$层所到达的纵坐标,$cost_{i}$表示在第$i$个城市买机器人的代价。

那么对每一条斜的对角线维护一个单调队列即可。

时间复杂度$O(n^2)$。

我还是没有实现它。

介绍一种dalao的思路。(第二个id叫Ghastlcon)的大佬,他的Luogu博客中这篇文章看不了了……

有一个小trick就是把下标从$0$到$n - 1$编号,这样子上面定义的$pos(i, j) = ((i - j) \% n + n) \% n$,这样子做前缀和的时候也比较方便。

其实我们发现$f$的第二维是没r用的,所以可以直接拿掉,因为在一个结束的位置并不影响在下一个开始的位置,我们要的只是这个最大值。

把前缀和$g$完整地写出来,有:$f_{i} = max(f_{j} + g_{i} - g_{j - 1} - cost_{j})  (1 \leq i - j \leq p - 1)$。

可以把之后与$i$有关的项拿到外面来,就可以用单调队列优化了。

时间复杂度$O(n^2)$。

Code:

#include <cstdio>
#include <cstring>
using namespace std; const int N = ; int n, m, k, a[N], g[N][N], f[N]; inline void read(int &X) {
X = ; char ch = ; int op = ;
for(; ch > ''|| ch < ''; ch = getchar())
if(ch == '-') op = -;
for(; ch >= '' && ch <= ''; ch = getchar())
X = (X << ) + (X << ) + ch - ;
X *= op;
} struct PriQueue {
int lst[N], pos[N], l, r; inline void init() {
l = , r = ;
} inline void push(int x, int val) {
for(; l <= r && lst[r] < val; --r);
lst[++r] = val, pos[r] = x;
} inline void pop(int p) {
for(; l <= r && pos[l] < p; ++l);
} } q[N]; inline int pos(int x, int len) {
return ((x - len) % n + n) % n;
} inline void chkMax(int &x, int y) {
if(y > x) x = y;
} int main() {
read(n), read(m), read(k);
for(int i = ; i < n; i++)
for(int j = ; j <= m; j++)
read(g[i][j]);
for(int i = ; i < n; i++) read(a[i]); for(int j = ; j <= m; j++)
for(int i = ; i < n; i++)
g[i][j] += g[(i + n - ) % n][j - ]; for(int i = ; i < n; i++) q[i].init(); for(int i = ; i < n; i++) {
int now = pos(i, -);
q[now].push(, -a[i]);
} memset(f, , sizeof(f)); f[] = ;
for(int i = ; i <= m; i++) {
for(int j = ; j < n; j++) {
int now = pos(j, i - );
chkMax(f[i], q[now].lst[q[now].l] + g[pos(j, )][i]);
} for(int j = ; j < n; j++) {
int now = pos(j, i - );
q[now].pop(i - k + );
q[now].push(i, f[i] - g[pos(j, )][i] - a[j]);
}
} printf("%d\n", f[m]);
return ;
}

Luogu 1070 道路游戏的更多相关文章

  1. [luogu 1070]道路游戏(NOIP2009T4)

    题目链接 题解: 题目描述好长啊.... 大概就是设一下$f[i]$表示第i秒的最大价值 首先枚举时间,然后因为机器人这一秒无论在哪里都是有可能的,所以要枚举一下每个点,又因为最多走p秒所以再枚举一下 ...

  2. [luogu]P1070 道路游戏[DP]

    [luogu]P1070 道路游戏 题目描述小新正在玩一个简单的电脑游戏.游戏中有一条环形马路,马路上有 n 个机器人工厂,两个相邻机器人工厂之间由一小段马路连接.小新以某个机器人工厂为起点,按顺时针 ...

  3. luogu P1070 道路游戏

    传送门 这里设\(f_i\)表示时刻\(i\)的答案 转移的话在\([i-p+1,i-1]\)之间枚举j,然后考虑从哪个点走过来 复杂度为\(O(n^3)\) // luogu-judger-enab ...

  4. 洛谷 P1070 道路游戏 解题报告

    P1070 道路游戏 题目描述 小新正在玩一个简单的电脑游戏. 游戏中有一条环形马路,马路上有\(n\)个机器人工厂,两个相邻机器人工厂之间由一小段马路连接.小新以某个机器人工厂为起点,按顺时针顺序依 ...

  5. 1070 Bash游戏 V4

    1070 Bash游戏 V4 基准时间限制:1 秒 空间限制:131072 KB 分值: 40 难度:4级算法题 有一堆石子共有N个.A B两个人轮流拿,A先拿.每次拿的数量最少1个,最多不超过对手上 ...

  6. 1070 Bash 游戏 V4

    传送门 1070 Bash游戏 V4   基准时间限制:1 秒 空间限制:131072 KB 分值: 40 难度:4级算法题 有一堆石子共有N个.A B两个人轮流拿,A先拿.每次拿的数量最少1个,最多 ...

  7. 洛谷P1070 道路游戏

    P1070 道路游戏 题目描述 小新正在玩一个简单的电脑游戏. 游戏中有一条环形马路,马路上有 n 个机器人工厂,两个相邻机器人工厂之间由一小段马路连接.小新以某个机器人工厂为起点,按顺时针顺序依次将 ...

  8. 洛谷 P1070 道路游戏 DP

    P1070 道路游戏 题意: 有一个环,环上有n个工厂,每个工厂可以生产价格为x的零钱收割机器人,每个机器人在购买后可以沿着环最多走p条边,一秒走一条,每条边不同时间上出现的金币是不同的,问如何安排购 ...

  9. 51 Nod 1070 Bash游戏v4(斐波那契博弈)

    这题的证明看不太懂,日后再重做... 1070 Bash游戏 V4  基准时间限制:1 秒 空间限制:131072 KB 分值: 40 难度:4级算法题  收藏  关注 有一堆石子共有N个.A B两个 ...

随机推荐

  1. IO模式调查利器blkiomon介绍

    本文链接地址: IO模式调查利器blkiomon介绍 blkiomon 是blktrace工具包带的一个方便用户了解IO情况的工具, 由于blktrace太专业,需要了解的IO协议栈的东西太多,blk ...

  2. Java 中的 JVM、堆和栈 -- 初步了解

    JVM -- Java Virtual Machine(Java虚拟机) —— 因为要说堆和栈,所以我们必须要先简单的说一下JVM.(JVM详细请找度娘啦~) 首先,我们都知道 java 一直宣传的口 ...

  3. tomcat原理解析(一):一个简单的实现

    tomcat原理解析(一):一个简单的实现 https://blog.csdn.net/qiangcai/article/details/60583330 2017年03月07日 09:54:27 逆 ...

  4. hadoop分布式快速搭建

    hadoop分布式快速搭建 1.配置主节点与从节点的ssh互信:[其中在主从节点主机的/etc/hosts文件中需绑定主机名ip间的映射关系; 如,192.168.1.113 node0 192.16 ...

  5. jmeter随机函数

    有些接口的字段,入参须唯一. 高并发压测的时候,这个比较棘手,可以用多个随机函数组合 如:两个__RandomString中间,夹个__Random ${__RandomString(2,qwerty ...

  6. libcurl 不支持https访问

    项目中使用libcurl 访问https的时候会报错,比如:“Unsupported protocol” 或者:“Protocol https not supported or disabled in ...

  7. mongodb基础学习10-手动预分片

    手动预分片是提前对分片创建一定数量足够使用的chunk,这样避免了IO上的压力 先对要演示的表进行分片 调用splitAt函数进行手动预分片,第一个参数指定要预分片的表,第二个参数指定分片规则,即当u ...

  8. mongodb基础学习9-分片

    分片和复制集不同,复制集是多个实例存储相同的内容,而分片是将内容存储到不同的分片上,不同分片存储的数据不同 下面看看具体的操作: 先启动两个片的实例: 再启动configsvr,要加上configsv ...

  9. C++17尝鲜:在 if 和 switch 语句中进行初始化

    初始化语句 在C++17中,类似于 for 语句,在 if 和 switch 语句的判断条件之前也能加上初始化语句,语法形式如下: if (初始化语句; 条件) 语句 else 语句 switch ( ...

  10. hadoop+zookeeper(ha架构搭建)

    http://blog.csdn.net/baidu_25820069/article/details/52225293 [条件所限,待验证]