bzoj1499 [NOI2005]瑰丽华尔兹 (单调队列优化DP)
来源:互联网 发布:好易网络电视apk 编辑:程序博客网 时间:2024/06/05 06:09
bzoj1499 [NOI2005]瑰丽华尔兹
原题地址:http://www.lydsy.com/JudgeOnline/problem.php?id=1499
题意:
舞厅是一个N行M列的矩阵,一些地方有障碍物,其他的则是空地。钢琴初始在(x,y),可以在空地上滑动,但不能撞上家具或滑出舞厅。每个时刻,钢琴都会倾斜的方向向相邻的方格滑动一格,相邻的方格可以是向东、向西、向南或向北的。
每个时刻可以让钢琴滑动或原地不动。给出每段时间的倾斜情况,钢琴最长的滑行路程。
数据范围
N,M,K <=200
(船体倾斜情况是按时间的区间来描述的,且从1开始计量时间,比如“在[1, 3]时间里向东倾斜,[4, 5]时间里向北倾斜”。因此K表示区间的数目,顺序描述K个时间区间,格式为:si ti di。表示在时间区间[si, ti]内,船体都是向di方向倾斜的。di为1, 2, 3, 4中的一个,依次表示北、南、西、东(分别对应矩阵中的上、下、左、右)。输入保证区间是连续的,即 s1 = 1 si = ti-1 + 1 (1 < i ≤ K) tK = T)
题解:
最开始能够想到的DP是对于每个时间点每个位置,但是肯定是会T的。
K的范围<=200,而在一个段内只能往同一个方向滑动,可以想到按段来DP。
此时有:(以向右倾斜为例)
dp[i][j][k] = max(dp[i][j’]+j-j’) (j-j’<=t-s+1且(i,j)与(i,j’)之间没有障碍)
这样的复杂度是O(n^2 M K)
现在考虑优化,要做到每次只取一次就能取出最大的dp[i][j’]+j-j’
显然对于每个j,dp[i][j’]+j-j’在变化,于是移项得:
dp[i][j][k] = max(dp[i][j’][k-1]+j-j’)
dp[i][j][k]-j = max(dp[i][j’][k-1]-j’)
转化为j,j’各在一边的情况,可以用单调队列来维护这个dp[i][j][k]-j ,每次取队首即可。
但是对于四种情况都要跑单调队列DP感觉还是非常繁琐,似乎要百行以上。
看了这位dalao的博客
把四种情况合起来写,就非常清爽了。
尤其是为了计算j-j’这个差值,因为并没有标明是行还是列,直接用一个累加器累加也是很巧的简化方式。
代码:
#include<cstdio>#include<iostream>#include<algorithm>#include<cstring>#include<queue>using namespace std;const int N=210;struct node{ int a,b; node(){} node(int a,int b):a(a),b(b){}}Q[N];//1 上 2下 3左 4右 int n,m,sx,sy,k,dp[N][N];int fx[5]={0,-1,1,0,},fy[5]={0,0,0,-1,1},ans=0;char s[N][N];void solve(int opt,int x,int y,int t){ int lf=0,rg=0; for(int i=0;x>=1&&x<=n&&y>=1&&y<=m;x+=fx[opt],y+=fy[opt],i++) { if(s[x][y]=='x') {lf=rg=0; continue;} int a=dp[x][y]; int b=i; while(lf<rg&&Q[rg].a-Q[rg].b<=a-b) rg--; Q[++rg].a=a; Q[rg].b=b; while(lf<rg&&(i-Q[lf+1].b)>t) lf++; dp[x][y]=Q[lf+1].a-Q[lf+1].b+i; ans=max(ans,dp[x][y]); }}int main(){ scanf("%d%d%d%d%d",&n,&m,&sx,&sy,&k); for(int i=1;i<=n;i++) scanf("%s",s[i]+1); memset(dp,-60,sizeof(dp)); dp[sx][sy]=0; for(int i=1;i<=k;i++) { int l,r,opt; scanf("%d%d%d",&l,&r,&opt); if(opt==1) for(int j=1;j<=m;j++) solve(1,n,j,r-l+1); else if(opt==2) for(int j=1;j<=m;j++) solve(2,1,j,r-l+1); else if(opt==3) for(int j=1;j<=n;j++) solve(3,j,m,r-l+1); else for(int j=1;j<=n;j++) solve(4,j,1,r-l+1); } printf("%d\n",ans); return 0;}
- 【bzoj1499】[NOI2005]瑰丽华尔兹(dp+单调队列优化)
- bzoj1499 [NOI2005]瑰丽华尔兹 (单调队列优化DP)
- bzoj1499 [NOI2005]瑰丽华尔兹(dp+单调队列)
- bzoj1499 [NOI2005]瑰丽华尔兹(luoguP2254)(dp+单调队列)
- [BZOJ1499][NOI2005][DP+优化]瑰丽华尔兹
- 【noi2005试题】瑰丽华尔兹 单调队列优化DP
- zstu3924 [NOI2005]瑰丽华尔兹 (单调队列dp)
- [NOI2005]瑰丽华尔兹 && dp单调队列
- 【DP】【单调队列】【NOI2005】瑰丽华尔兹
- [BZOJ1499][NOI2005]瑰丽华尔兹
- [bzoj1499][NOI2005]瑰丽华尔兹
- BZOJ1499: [NOI2005]瑰丽华尔兹
- bzoj1499: [NOI2005]瑰丽华尔兹
- NOI2005瑰丽华尔兹-单调队列
- 【NOI2005T1】瑰丽华尔兹-DP单调队列优化
- [bzoj1499][NOI2005] 瑰丽华尔兹 代码
- BZOJ 1499 [NOI2005]瑰丽华尔兹 动态规划(+单调队列)
- BZOJ 1499 NOI2005 瑰丽华尔兹 单调队列
- 51nod 1220 约数之和
- dfs学习之扫雷问题
- 数人云|使微服务、容器趋向完美——Serverless架构你应当知道的二三事
- Linux C编程第四章的10个问题以及解决方案
- 树莓派进行socket掉线重连出现的问题
- bzoj1499 [NOI2005]瑰丽华尔兹 (单调队列优化DP)
- 如何如何引领一名普通程序员走向优秀?
- 神经网络梯度下降优化算法及初始化方法小结
- 《数据库系统概念》学习笔记
- sass相关介绍
- C语言语句
- upD79F8513A(NEC)或upD78F0511A(NEC)之电源电压检测
- Linux基础练习(二)
- Linux 磁盘与文件系统 —— 基础知识(二)