题外话:题目极好,做题体验极差

题面:[NOI2005]瑰丽华尔兹

题解:

F[t][i][j]表示第t时刻钢琴位于(i,j)时的最大路程
F[t][i][j]=max(F[t-1][i][j],F[t-1][a][b]+1) (mp[i][j]可以到达,(a,b)直接到(i,j)之间没有家具,即路径合法)
因为船的倾斜是连续的,所以可以考虑按时间段来进行dp
F[t][i][j]表示前t个时间段结束后,钢琴位于(i,j)的最大路程
F[t][i][j]=max(F[t][i][j],F[t-1][a][b]+Dis(a,b,i,j)) (mp[i][j]可达,Dis(a,b,i,j)<=T[t]-S[t]+1,(a,b)直接到(i,j)之间没有家具,即路径合法)
考虑使用单调队列优化dp
以下“OK”意味着mp[i][j]不出地图,且(i,j)上无家具,是可以到达的合法位置,且路径合法
路径合法可以通过在单调队列时遇到mp[i][j]=='x'的情况直接清空队列来快速实现,当然也可以通过写前缀和来判断实现
注意在写单调队列时入队应该放在维护F[t][i][j]前,因为可以停留在(i,j)
Case 1:D[t]==1
此时船向北倾斜,则b=j(i大到i小)
F[t][i][j]=max(F[t][i][j],F[t-1][a][j]+a-i) (OK,a-i<=T[t]-S[t]+1)
即维护:max(F[t-1][a][j]+a)-i (a<=T[t]-S[t]+1+i)
Case 2:D[t]==2
此时船向南倾斜,则b=j(i小到i大)
F[t][i][j]=max(F[t][i][j],F[t-1][a][j]+i-a) (OK,i-a<=T[t]-S[t]+1)
即维护:max(F[t-1][a][j]-a)+i (a>=i-T[t]+S[t]-1)
Case 3:D[t]==3
此时船向西倾斜,则a=i(j从大到小)
F[t][i][j]=max(F[t][i][j],F[t-1][i][b]+b-j) (OK,b-j<=T[t]-S[t]+1)
即维护:max(F[t-1][i][b]+b)-j(b<=T[t]-S[t]+1+j)
Case 4:D[t]==4
此时船向东倾斜,则a=i(j从小到大)
F[t][i][j]=max(F[t][i][j],F[t-1][i][b]+j-b) (OK,j-b<=T[t]-S[t]+1)
即维护:max(F[t-1][i][b]-b)+j (b>=j-T[t]+S[t]-1)
对以上使用单调队列进行优化

代码:

  1. #include<cstdio>
  2. #include<iostream>
  3. #define max(a,b) ((a)>(b)?(a):(b))
  4. #define min(a,b) ((a)<(b)?(a):(b))
  5. using namespace std;
  6. const int maxn=,maxm=,maxk=,maxt=4e4+;
  7. const int inf=<<;
  8. int N,M,K,X0,Y0,S[maxk],T[maxk],D[maxk];
  9. int F[maxk][maxn][maxm],f1,f2,ans=;
  10. char mp[maxn][maxm];
  11. struct Node{ int data,x; }que[maxn];
  12. int main(){
  13. scanf("%d%d%d%d%d",&N,&M,&X0,&Y0,&K);
  14. for(int i=;i<=N;i++)
  15. scanf("%s",mp[i]+);
  16. for(int i=;i<=K;i++)
  17. scanf("%d%d%d",&S[i],&T[i],&D[i]);
  18. for(int t=;t<=K;t++)
  19. for(int i=;i<=N;i++)
  20. for(int j=;j<=M;j++)
  21. F[t][i][j]=-inf;
  22. for(int t=;t<=K;t++)
  23. F[t][X0][Y0]=;
  24. for(int t=;t<=K;t++){
  25. if(D[t]==){
  26. for(int j=;j<=M;j++){
  27. f1=,f2=;
  28. for(int i=N;i>=;i--){
  29. if(mp[i][j]=='x') {
  30. f1=,f2=;
  31. continue;
  32. }
  33. while(f1<=f2 && que[f1].x>T[t]-S[t]++i) f1++;
  34. while(f1<=f2 && F[t-][i][j]+i>=que[f2].data) f2--;
  35. que[++f2].data=F[t-][i][j]+i; que[f2].x=i;
  36. if(f1<=f2) F[t][i][j]=max(F[t][i][j],que[f1].data-i);
  37. }
  38. }
  39. }
  40. else if(D[t]==){
  41. for(int j=;j<=M;j++){
  42. f1=,f2=;
  43. for(int i=;i<=N;i++){
  44. if(mp[i][j]=='x') {
  45. f1=,f2=;
  46. continue;
  47. }
  48. while(f1<=f2 && que[f1].x<i-T[t]+S[t]-) f1++;
  49. while(f1<=f2 && F[t-][i][j]-i>=que[f2].data) f2--;
  50. que[++f2].data=F[t-][i][j]-i; que[f2].x=i;
  51. if(f1<=f2) F[t][i][j]=max(F[t][i][j],que[f1].data+i);
  52. }
  53. }
  54. }
  55. else if(D[t]==){
  56. for(int i=;i<=N;i++){
  57. f1=,f2=;
  58. for(int j=M;j>=;j--){
  59. if(mp[i][j]=='x') {
  60. f1=,f2=;
  61. continue;
  62. }
  63. while(f1<=f2 && que[f1].x>T[t]-S[t]++j) f1++;
  64. while(f1<=f2 && F[t-][i][j]+j>=que[f2].data) f2--;
  65. que[++f2].data=F[t-][i][j]+j; que[f2].x=j;
  66. if(f1<=f2) F[t][i][j]=max(F[t][i][j],que[f1].data-j);
  67. }
  68. }
  69. }
  70. else{// D[t]==4
  71. for(int i=;i<=N;i++){
  72. f1=,f2=;
  73. for(int j=;j<=M;j++){
  74. if(mp[i][j]=='x') {
  75. f1=,f2=;
  76. continue;
  77. }
  78. while(f1<=f2 && que[f1].x<j-T[t]+S[t]-) f1++;
  79. while(f1<=f2 && F[t-][i][j]-j>=que[f2].data) f2--;
  80. que[++f2].data=F[t-][i][j]-j; que[f2].x=j;
  81. if(f1<=f2) F[t][i][j]=max(F[t][i][j],que[f1].data+j);
  82. }
  83. }
  84. }
  85. }
  86. for(int i=;i<=N;i++)
  87. for(int j=;j<=M;j++)
  88. ans=max(ans,F[K][i][j]);
  89. printf("%d\n",ans);
  90. return ;
  91. }

By:AlenaNuna

单调队列优化DP || [NOI2005]瑰丽华尔兹 || BZOJ 1499 || Luogu P2254的更多相关文章

  1. 单调队列优化DP || [Poi2014]Little Bird || BZOJ 3831 || Luogu P3572

    题面:[POI2014]PTA-Little Bird 题解: N<=1e6 Q<=25F[i]表示到达第i棵树时需要消耗的最小体力值F[i]=min(F[i],F[j]+(D[j]> ...

  2. P4381 [IOI2008]Island(基环树+单调队列优化dp)

    P4381 [IOI2008]Island 题意:求图中所有基环树的直径和 我们对每棵基环树分别计算答案. 首先我们先bfs找环(dfs易爆栈) 蓝后我们处理直径 直径不在环上,就在环上某点的子树上 ...

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

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

  4. bzoj 1499 [NOI2005]瑰丽华尔兹——单调队列优化dp

    题目:https://www.lydsy.com/JudgeOnline/problem.php?id=1499 简单的单调队列优化dp.(然而当时却WA得不行.今天总算填了坑) 注意滚动数组赋初值应 ...

  5. 2018.09.10 bzoj1499: [NOI2005]瑰丽华尔兹(单调队列优化dp)

    传送门 单调队列优化dp好题. 这题其实很简单. 我们很容易想到一个O(T∗n∗m)" role="presentation" style="position: ...

  6. bzoj1499: [NOI2005]瑰丽华尔兹&&codevs1748 单调队列优化dp

    这道题 网上题解还是很多很好的 强烈推荐黄学长 码风真的好看 神犇传送门 学习学习 算是道单调队列优化dp的裸题吧 #include<cstdio> #include<cstring ...

  7. CF939F Cutlet (单调队列优化DP)

    题目大意:要煎一块有两个面的肉,只能在一段k不相交的时间段$[l_{i},r_{i}]$内翻转,求$2*n$秒后,保证两个面煎的时间一样长时,需要最少的翻转次数,$n<=100000$,$k&l ...

  8. 「学习笔记」单调队列优化dp

    目录 算法 例题 最大子段和 题意 思路 代码 修剪草坪 题意 思路 代码 瑰丽华尔兹 题意 思路 代码 股票交易 题意 思路 代码 算法 使用单调队列优化dp 废话 对与一些dp的转移方程,我们可以 ...

  9. 【笔记篇】单调队列优化dp学习笔记&&luogu2569_bzoj1855股票交♂易

    DP颂 DP之神 圣洁美丽 算法光芒照大地 我们怀着 崇高敬意 跪倒在DP神殿里 你的复杂 能让蒟蒻 试图入门却放弃 在你光辉 照耀下面 AC真心不容易 dp大概是最经久不衰 亘古不化的算法了吧. 而 ...

随机推荐

  1. 浏览器端-W3School-JavaScript:JavaScript Date 对象

    ylbtech-浏览器端-W3School-JavaScript:JavaScript Date 对象 1.返回顶部 1. Date 对象 Date 对象用于处理日期和时间. 创建 Date 对象的语 ...

  2. 自定义view防支付成功页面

    package com.loaderman.customviewdemo; import android.content.Context; import android.graphics.Canvas ...

  3. android开源图表库MPAndroidChart(曲线图、直方图、饼状图)

    github地址:https://github.com/PhilJay/MPAndroidChart 添加依赖: Add the following to your project level bui ...

  4. 代码实现:编写一个函数,输入n为偶数时,调用函数求1/2+1/4+...+1/n,当输入n为奇数时,调用函数1/1+1/3+...+1/n

    import java.util.Scanner; //编写一个函数,输入n为偶数时,调用函数求1/2+1/4+...+1/n,当输入n为奇数时,调用函数1/1+1/3+...+1/n public ...

  5. LinkedList简介

    原文:https://blog.csdn.net/GongchuangSu/article/details/51527042 LinkedList简介 LinkedList 是一个继承于Abstrac ...

  6. Visual Studio 2017 远程调试

    当你将.NET程序发布到不同机子时候,想要进行调试,但机子不足以安装VS或安装VS麻烦,可以考虑使用远程调试,这里以C#项目为例,asp.net方法略有不同 原理: 首先安装VS远程调试工具,有俩种安 ...

  7. 安装mangodb

    1.配置yum源 [root@www ~]# cat /etc/yum.repos.d/mongodb-org-3.4.repo [mongodb-org-3.4] name=MongoDB Repo ...

  8. 使用var提升变量声明

    使用var 定义变量还会提升变量声明,即使用var定义:function hh(){ console.log(a); var a = 'hello world';}hh() //undefined 不 ...

  9. oop理论

    三大特性: 封装:把对象的属性和行为独立的一个整体,并尽可能的隐藏对象内部实现细节.增加安全性. 继承:从已有的类中派生出新的类,称为子类,子类继承父类的属性和行为,并能根据自己的需求扩展出新的行为. ...

  10. docker 安装 nexus

    docker pull sonatype/nexus3 用docker-compose 部署 创建目录 /usr/local/docker/nexus 在目录下 创建docker-compose.ym ...