嘟嘟嘟




这题大家应该都做过,就是暴力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. 史上最全的 Python 3 类型转换指南

    int 支持转换为 int 类型的,仅有 float.str.bytes,其他类型均不支持. float -> int 会去掉小数点及后面的数值,仅保留整数部分. int(-12.94) # - ...

  2. C 语言精髓之变参函数

    我们以 printf 这个 very 熟悉的函数为例,来分析一下变参函数.先看下 printf 函数的定义: int printf(const char *fmt, ...) { int i; int ...

  3. c# DataSet转换为Json

    /// <summary> /// DataSet转换为Json /// </summary> /// <param name="dataSet"&g ...

  4. Web Service 与WebAPI 的区别

    Web Servise: web service 是一种跨编程语言和跨操作系统平台的远程调用技术. 所谓跨编程语言和跨操作系统平台,就是说服务器端程序采用Java编写,客户端程序则可以采用其他编程语言 ...

  5. Ajax事件,方法

    1\ready:事件:使用ready()来使函数在文档加载后可用 $(document).ready(funcation(){ 函数体 }) 2\click事件:当单机元素时,使用 3\focus事件 ...

  6. (2)Microsoft office Word 2013版本操作入门_快速选中

    1.快速选中一行 .一段文字: 1.1光标在一行内,双击会选中一个词组.快速点击三下会选中一段, 1.2 鼠标移动到行首,单击击会选中一行,双击选中一段. 1.3 选择全部内容 Ctrl+A  , 1 ...

  7. vi命令详解2

    介绍 vi编辑器是所有Unix及Linux系统下标准的编辑器,它的强大不逊色于任何最新的文本编辑器,这里只是简单地介绍一下它的用法和一小部分指令. 1.vi的基本概念 vi可以分为三种状态,分别如下: ...

  8. TestOps宣言

    TestOps   TestOps离不开敏捷 TestOps是测试驱动的一种延伸,它强调测试人员与运维人员沟通协作规范化的实践模式. DevOps的持续集成与持续交付,实现了从代码到服务的快速落地.而 ...

  9. JavaScript有这几种测试

    译者按: 也许你讨厌测试,但是你不得不面对它,所以至少区分一下单元测试.集成测试与功能测试?对吧... 原文: What are Unit Testing, Integration Testing a ...

  10. HDU5543(SummerTrainingDay03-O DP)

    Pick The Sticks Time Limit: 15000/10000 MS (Java/Others)    Memory Limit: 65535/65535 K (Java/Others ...