[NOI 2005] 瑰丽华尔兹:dp+单调队列
来源:互联网 发布:js filter 实现 编辑:程序博客网 时间:2024/06/05 22:35
状态转移方程,以船体向南倾斜为例,其中
注意到需要考虑的状态是同一列上的一段区间,我想到用线段树优化转移。每行每列各两棵,维护
具有可行性,但是能否做得更好呢?
贺神说它要用单调队列,我咋没用上呢?
确定递推顺序的时候,发现查询的区间有许多重叠,就像——滑动窗口。再者,同样以南为例,按照i递增的顺序递推,如果
那么
开始写代码吧。东南西北四种对称情形,抽取它们的内在结构,避免冗长的代码——这一点黄学长做得比我好。截至目前(2016年9月10日晚),我的程序是bzoj上倒数第三慢的,推测主要原因来自于三维数组寻址。
昨天晚上写好了,但是有bug——某处f[i][j][k-1]
误作f[i][j][k]
。用当年的数据,也就30分了。我本应该发现——之前因为另一个问题输出中间变量,和我预期的不一样。但是由于答案正确,没有深究。注意细节。关注每一处异常。
#include <cstdio>#include <cstring>#include <cmath>#include <cctype>#include <algorithm>using namespace std;const int MAX_N = 200, MAX_M = 200, MAX_K = 200+1, INF = 1<<30;int N, M, head, tail, f[MAX_N][MAX_M][MAX_K];char m[MAX_N][MAX_M];struct Point { int i, j; int operator-(const Point& rhs) const { return abs(i - rhs.i + j - rhs.j); } int get_f(int k) { return f[i][j][k]; }} q[MAX_N];void upd(int i, int j, int k, int t){ if (m[i][j] == 'x') { tail = head; return; } Point p = (Point){i, j}; while (head != tail && q[head] - p > t) ++head; while (head != tail && q[tail-1].get_f(k-1) + (q[tail-1] - p) <= f[i][j][k-1]) --tail; q[tail++] = p; f[i][j][k] = q[head].get_f(k-1) + (q[head] - p); }inline void north(int k, int t){ for (int j = 0; j < M; ++j) { head = tail = 0; for (int i = N-1; i >= 0; --i) upd(i, j, k, t); }}inline void south(int k, int t){ for (int j = 0; j < M; ++j) { head = tail = 0; for (int i = 0; i < N; ++i) upd(i, j, k, t); }}inline void east(int k, int t){ for (int i = 0; i < N; ++i) { head = tail = 0; for (int j = 0; j < M; ++j) upd(i, j, k, t); }}inline void west(int k, int t){ for (int i = 0; i < N; ++i) { head = tail = 0; for (int j = M-1; j >= 0; --j) upd(i, j, k, t); }}template<typename T>void read(T& x){ x = 0; char c = getchar(); while (!isdigit(c)) c = getchar(); while (isdigit(c)) { x = x*10 + c - '0'; c = getchar(); }}int main(){ int x, y, K; read(N); read(M); read(x); read(y); read(K); for (int i = 0; i < N; ++i) for (int j = 0; j < M; ++j) f[i][j][0] = -INF; f[x-1][y-1][0] = 0; for (int i = 0; i < N; ++i) scanf("%s", m[i]); int s, t, d, tm; for (int i = 1; i <= K; ++i) { read(s); read(t); read(d); tm = t-s+1; switch (d) { case 1: north(i, tm); break; case 2: south(i, tm); break; case 3: west(i, tm); break; case 4: east(i, tm); break; } } int ans = -INF; for (int i = 0; i < N; ++i) for (int j = 0; j < M; ++j) ans = max(ans, f[i][j][K]); printf("%d\n", ans); return 0;}
0 0
- NOI 2005 瑰丽华尔兹(DP+单调队列)
- [NOI 2005] 瑰丽华尔兹:dp+单调队列
- [BZOJ 1499][NOI 2005]瑰丽华尔兹(DP+单调队列优化)
- zstu3924 [NOI2005]瑰丽华尔兹 (单调队列dp)
- [NOI2005]瑰丽华尔兹 && dp单调队列
- 【DP】【单调队列】【NOI2005】瑰丽华尔兹
- 【NOI2005T1】瑰丽华尔兹-DP单调队列优化
- bzoj1499 [NOI2005]瑰丽华尔兹(dp+单调队列)
- NOI2005瑰丽华尔兹-单调队列
- 【noi2005试题】瑰丽华尔兹 单调队列优化DP
- wikioi-1748 瑰丽华尔兹 -单调队列优化DP
- 【bzoj1499】[NOI2005]瑰丽华尔兹(dp+单调队列优化)
- bzoj1499 [NOI2005]瑰丽华尔兹 (单调队列优化DP)
- bzoj1499 [NOI2005]瑰丽华尔兹(luoguP2254)(dp+单调队列)
- BZOJ 1499 NOI2005 瑰丽华尔兹 单调队列
- [DP 暴力 || ST表 || 单调队列] BZOJ 1499 [NOI2005]瑰丽华尔兹
- BZOJ 1499 [NOI2005]瑰丽华尔兹 动态规划(+单调队列)
- [BZOJ1499][NOI2005][DP+优化]瑰丽华尔兹
- Google浏览器划词翻译
- LeetCode: Maximum Subarray
- android实现刮刮卡
- redis java下的使用
- 自定义圆形imageView
- [NOI 2005] 瑰丽华尔兹:dp+单调队列
- hdu 5875 单调栈+离线
- Python相对、绝对导入浅析
- hdu 5873
- 设置读写分离后数据同步的配置方法
- Google 的开源技术protobuf 简介与例子
- LeetCode-Roman to Integer
- 卷积
- C/C++中static关键字详解