嘟嘟嘟




这题大家应该都做过,就是暴力dp+单调队列优化。




dp方程其实很好想,最初是这样的:dp[t][i][j]表示时刻\(t\)后,走到\((i, j)\)格子的最远路程,于是就有:

\[dp[t][i][j] = max\{ dp[t - 1][px][py] \} + 1
\]

但这是\(O(Tn ^ 2)\)的,不仅会TLE,还能MLE。




接着看题,发现给得\(K\)没用上。想一下发现\(K\)的特点是同一时间区间的移动方向是一样的,于是我们把第一维改成第\(k\)个时间区间,转移方程就变成了:

\[dp[k][i][j] = max_{h = 1} ^ {len}\{ dp[k - 1][i - dx[d]][j - dy[d]] + dis(i, j, i - dx[d], j - dy[d])\}
\]

\(len\)表示区间长度。

方程可能丑了点,但意思就是枚举这个点能在这个时间段内从哪儿转移过来,然后就是对应的dp值加上这两点之间的距离。

注意如果有的格子不能走,就不能从这里转移。

复杂度\(O(kn ^ 3)\)。




于是就有单调队列优化啦。

对于一个点,这一步能转移到他的实际上就是x或y方向上连续的一段dp值,于是我们把这些dp值放进单调队列里就行了。

这样优化到\(O(kn ^ 2)\),就过了。

需要注意的是,我们要用k - 1时刻更新k时刻的答案,因此先把dp[x][y]放入队列,再用队首更新dp值。这样就保证了放进去的dp值一定是上一个时刻的。

#include<cstdio>
#include<iostream>
#include<cmath>
#include<algorithm>
#include<cstring>
#include<cstdlib>
#include<cctype>
#include<vector>
#include<stack>
#include<queue>
using namespace std;
#define enter puts("")
#define space putchar(' ')
#define Mem(a, x) memset(a, x, sizeof(a))
#define In inline
typedef long long ll;
typedef double db;
const int INF = 0x3f3f3f3f;
const db eps = 1e-8;
const int maxn = 205;
inline ll read()
{
ll ans = 0;
char ch = getchar(), last = ' ';
while(!isdigit(ch)) last = ch, ch = getchar();
while(isdigit(ch)) ans = (ans << 1) + (ans << 3) + ch - '0', ch = getchar();
if(last == '-') ans = -ans;
return ans;
}
inline void write(ll x)
{
if(x < 0) x = -x, putchar('-');
if(x >= 10) write(x / 10);
putchar(x % 10 + '0');
} int n, m, sx, sy, K;
char a[maxn][maxn];
struct Node
{
int L, R, dir;
}t[maxn];
int dp[maxn][maxn]; struct Que
{
int val, x, y;
}q[maxn];
int l = 1, r = 0;
const int dx[] = {0, -1, 1, 0, 0}, dy[] = {0, 0, 0, -1, 1};
In bool check(int x, int y) {return x && x <= n && y && y <= m;}
In int dis(int xa, int ya, int xb, int yb) {return abs(xa - xb) + abs(ya - yb);}
In void solve(int x, int y, int d, int len)
{
l = 1; r = 0;
while(check(x, y))
{
if(a[x][y] == 'x') l = 1, r = 0;
else
{
while(l <= r && q[r].val + dis(x, y, q[r].x, q[r].y) < dp[x][y]) --r;
q[++r] = (Que){dp[x][y], x, y};
while(l <= r && dis(x, y, q[l].x, q[l].y) > len) ++l;
dp[x][y] = q[l].val + dis(x, y, q[l].x, q[l].y);
}
x += dx[d]; y += dy[d];
}
} int main()
{
n = read(); m = read(); sx = read(), sy = read(), K = read();
for(int i = 1; i <= n; ++i) scanf("%s", a[i] + 1);
for(int i = 1; i <= K; ++i) t[i].L = read(), t[i].R = read(), t[i].dir = read();
Mem(dp, -0x3f); dp[sx][sy] = 0;
for(int i = 1; i <= K; ++i)
{
if(t[i].dir == 1) for(int j = 1; j <= m; ++j) solve(n, j, t[i].dir, t[i].R - t[i].L + 1);
if(t[i].dir == 2) for(int j = 1; j <= m; ++j) solve(1, j, t[i].dir, t[i].R - t[i].L + 1);
if(t[i].dir == 3) for(int j = 1; j <= n; ++j) solve(j, m, t[i].dir, t[i].R - t[i].L + 1);
if(t[i].dir == 4) for(int j = 1; j <= n; ++j) solve(j, 1, t[i].dir, t[i].R - t[i].L + 1);
}
int ans = 0;
for(int i = 1; i <= n; ++i)
for(int j = 1; j <= m; ++j) ans = max(ans, dp[i][j]);
write(ans), enter;
}

[NOI2005]瑰丽华尔兹的更多相关文章

  1. NOI2005瑰丽华尔兹

    1499: [NOI2005]瑰丽华尔兹 Time Limit: 3 Sec  Memory Limit: 64 MBSubmit: 893  Solved: 508[Submit][Status] ...

  2. bzoj1499[NOI2005]瑰丽华尔兹 单调队列优化dp

    1499: [NOI2005]瑰丽华尔兹 Time Limit: 3 Sec  Memory Limit: 64 MBSubmit: 1802  Solved: 1097[Submit][Status ...

  3. luogu P2254 [NOI2005]瑰丽华尔兹

    题目链接 luogu P2254 [NOI2005]瑰丽华尔兹 题解 为什么我我我不放放放bzoj的链接呢? 因为打的暴力啊,然后bzojT了呀QAQQQQQ(逃 然后luogu竟然过了呀呀呀 dp[ ...

  4. 【BZOJ1499】[NOI2005]瑰丽华尔兹 单调队列+DP

    [BZOJ1499][NOI2005]瑰丽华尔兹 Description 你跳过华尔兹吗?当音乐响起,当你随着旋律滑动舞步,是不是有一种漫步仙境的惬意?众所周知,跳华尔兹时,最重要的是有好的音乐.但是 ...

  5. [Bzoj1499][NOI2005]瑰丽华尔兹[简单DP]

    1499: [NOI2005]瑰丽华尔兹 Time Limit: 3 Sec  Memory Limit: 64 MBSubmit: 1714  Solved: 1042[Submit][Status ...

  6. 单调队列优化DP || [NOI2005]瑰丽华尔兹 || BZOJ 1499 || Luogu P2254

    题外话:题目极好,做题体验极差 题面:[NOI2005]瑰丽华尔兹 题解: F[t][i][j]表示第t时刻钢琴位于(i,j)时的最大路程F[t][i][j]=max(F[t-1][i][j],F[t ...

  7. P2254 [NOI2005]瑰丽华尔兹

    链接P2254 [NOI2005]瑰丽华尔兹 首先有个很朴素的\(dp\),设\(f_{i,j,k}\)表示\(k\)时刻地点\(i,j\)的最长长度. 然后这样不能优化,考虑利用一段连续时间是同一个 ...

  8. 题解-[NOI2005]瑰丽华尔兹

    题解-[NOI2005]瑰丽华尔兹 [NOI2005]瑰丽华尔兹 \(n\times m\) 的矩阵.以 \((x,y)\) 为起点.一共 \(k\) 段时间,每段时间为 \([s_i,t_i](t_ ...

  9. BZOJ 1499 [NOI2005] 瑰丽华尔兹 | 单调队列优化DP

    BZOJ 1499 瑰丽华尔兹 | 单调队列优化DP 题意 有一块\(n \times m\)的矩形地面,上面有一些障碍(用'#'表示),其余的是空地(用'.'表示).每时每刻,地面都会向某个方向倾斜 ...

  10. BZOJ1499:[NOI2005]瑰丽华尔兹(DP,单调队列)

    Description 你跳过华尔兹吗?当音乐响起,当你随着旋律滑动舞步,是不是有一种漫步仙境的惬意?众所周知,跳华尔兹时,最重要的是有好的音乐.但是很少有几个人知道,世界上最伟大的钢琴家一生都漂泊在 ...

随机推荐

  1. [java]我的数据在哪里?——数据的内存模型

    在编写程序时,我们也许会有这样一个问题,我们编写的程序中的数据运行时,会保存在哪里呢?简单直接的回答可能是——内存.这个回答在多数情况下可能都是对的,但事实上并不准确,我们都知道内存,即随机访问存储器 ...

  2. C++ 输入、输出运算符重载

    C++ 能够使用流提取运算符 >> 和流插入运算符 << 来输入和输出内置的数据类型.我们可以重载流提取运算符和流插入运算符来操作对象等用户自定义的数据类型. 在这里,有一点很 ...

  3. Ubuntu下将现有的文件打包成deb包

    转自:http://www.linuxidc.com/Linux/2008-04/12297.htm deb是Debian Linux的软件包格式.一般来说是需要通过编译源码然后制作deb包,今天由于 ...

  4. EF SaveChanges() 报错(转载)

    最佳答案 报这个错是因为,提交了主键重复的数据,虽然未提交到数据库中 但是现在的EF上下文中已经包含了我提交的数据,下次在提交正确数据时, 原来添加到上下文中的数据依然还在..如何处理这个问题呢?   ...

  5. [转]group by 后使用 rollup 子句总结

    group by 后使用 rollup 子句总结 一.如何理解group by 后带 rollup 子句所产生的效果 group by 后带 rollup 子句的功能可以理解为:先按一定的规则产生多种 ...

  6. bootstrap-multiselect 多选

    官方教程 http://www.kuitao8.com/demo/20140224/1/bootstrap-multiselect-master/index.html 使用方法: 第一步引用样式以及相 ...

  7. WebFrom 小程序【条件查询与分页整合】

    将前面的条件查询功能与分页显示整合到一个页面中 <%@ Page Language="C#" AutoEventWireup="true" CodeFil ...

  8. Git实战手册(三): stash解惑与妙用

    0. 介绍 教程所示图片使用的是 github 仓库图片,网速过慢的朋友请移步原文地址 有空就来看看个人技术小站, 我一直都在 在实际项目开发中,总会遇到代码写到一半(没法去打commit),去开启新 ...

  9. 卷积神经网络CNNs的理解与体会

    https://blog.csdn.net/shijing_0214/article/details/53143393 孔子说过,温故而知新,时隔俩月再重看CNNs,当时不太了解的地方,又有了新的理解 ...

  10. 单元测试工具Junit浅谈

    什么是单元测试?   写了一个类和一些方法,给别人用,会不会有bug?那就测一下这些方法吧 怎么测?   用main方法测?不能一起运行,需要人为观察输出是否正确,测试效率低 单元测试能带来什么好处? ...