【BZOJ1499】瑰丽华尔兹(动态规划)

题面

BZOJ

题解

先写部分分

设\(f[t][i][j]\)表示当前在\(t\)时刻,位置在\(i,j\)时走的最多的步数

这样子每一步要么停要么走

时间复杂度\(O(nmt)\)

得分\(40~70\)分

(据说这样能过???)

#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<cmath>
#include<algorithm>
#include<set>
#include<map>
#include<vector>
#include<queue>
using namespace std;
#define ll long long
#define RG register
#define MAX 210
inline int read()
{
RG int x=0,t=1;RG char ch=getchar();
while((ch<'0'||ch>'9')&&ch!='-')ch=getchar();
if(ch=='-')t=-1,ch=getchar();
while(ch<='9'&&ch>='0')x=x*10+ch-48,ch=getchar();
return x*t;
}
char g[MAX][MAX];
int ans,n,m,X,Y,K,L[MAX],R[MAX],D[MAX];
int d[5][2]={0,0,-1,0,1,0,0,-1,0,1};
int f[2][MAX][MAX],T[MAX*MAX];
int main()
{
n=read();m=read();X=read();Y=read();K=read();
for(int i=1;i<=n;++i)scanf("%s",g[i]+1);
for(int i=1;i<=K;++i)L[i]=read(),R[i]=read(),D[i]=read();
for(int i=1;i<=K;++i)
for(int j=L[i];j<=R[i];++j)T[j]=D[i];
memset(f,-1,sizeof(f));
f[0][X][Y]=0;
int nw=1,pw=0;
for(int tt=1;tt<=R[K];++tt,nw^=1,pw^=1)
{
for(int i=1;i<=n;++i)
for(int j=1;j<=m;++j)f[nw][i][j]=-1;
for(int i=1;i<=n;++i)
for(int j=1;j<=m;++j)
{
if(f[pw][i][j]==-1)continue;
int xx=i+d[T[tt]][0],yy=j+d[T[tt]][1];
f[nw][i][j]=max(f[nw][i][j],f[pw][i][j]);
if(xx<1||yy<1||xx>n||yy>m)continue;
if(g[xx][yy]=='x')continue;
f[nw][xx][yy]=max(f[nw][xx][yy],f[pw][i][j]+1);
}
}
for(int i=1;i<=n;++i)
for(int j=1;j<=m;++j)
ans=max(ans,f[R[K]&1][i][j]);
printf("%d\n",ans);
return 0;
}

发现转移可以用单调队列优化

于是分四种情况进行讨论

用单调队列优化转移即可

#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<cmath>
#include<algorithm>
#include<set>
#include<map>
#include<vector>
#include<queue>
using namespace std;
#define ll long long
#define RG register
#define MAX 210
inline int read()
{
RG int x=0,t=1;RG char ch=getchar();
while((ch<'0'||ch>'9')&&ch!='-')ch=getchar();
if(ch=='-')t=-1,ch=getchar();
while(ch<='9'&&ch>='0')x=x*10+ch-48,ch=getchar();
return x*t;
}
char g[MAX][MAX];
int ans,n,m,X,Y,K,L[MAX],R[MAX],D[MAX];
int d[5][2]={0,0,-1,0,1,0,0,-1,0,1};
int f[2][MAX][MAX],T[MAX*MAX];
int Q[MAX],h,t;
int main()
{
n=read();m=read();X=read();Y=read();K=read();
for(int i=1;i<=n;++i)scanf("%s",g[i]+1);
for(int i=1;i<=K;++i)L[i]=read(),R[i]=read(),D[i]=read();
for(int i=1;i<=n;++i)
for(int j=1;j<=m;++j)f[0][i][j]=-1e9;
f[0][X][Y]=0;
int nw=1,pw=0;
for(int tt=1;tt<=K;++tt,nw^=1,pw^=1)
{
for(int i=1;i<=n;++i)
for(int j=1;j<=m;++j)f[nw][i][j]=f[pw][i][j];
if(D[tt]==1)
for(int j=1;j<=m;++j)
{
h=1;t=0;
for(int i=n;i;--i)
{
if(g[i][j]=='x'){h=1;t=0;continue;}
while(h<=t&&Q[h]-i>R[tt]-L[tt]+1)++h;
while(h<=t&&f[pw][Q[t]][j]+Q[t]<=f[pw][i][j]+i)--t;
Q[++t]=i;
if(h<=t)f[nw][i][j]=f[pw][Q[h]][j]+Q[h]-i;
}
}
else if(D[tt]==2)
for(int j=1;j<=m;++j)
{
h=1;t=0;
for(int i=1;i<=n;++i)
{
if(g[i][j]=='x'){h=1;t=0;continue;}
while(h<=t&&i-Q[h]>R[tt]-L[tt]+1)++h;
while(h<=t&&f[pw][Q[t]][j]-Q[t]<=f[pw][i][j]-i)--t;
Q[++t]=i;
if(h<=t)f[nw][i][j]=f[pw][Q[h]][j]+i-Q[h];
}
}
else if(D[tt]==3)
for(int i=1;i<=n;++i)
{
h=1;t=0;
for(int j=m;j;--j)
{
if(g[i][j]=='x'){h=1;t=0;continue;}
while(h<=t&&Q[h]-j>R[tt]-L[tt]+1)++h;
while(h<=t&&f[pw][i][Q[t]]+Q[t]<=f[pw][i][j]+j)--t;
Q[++t]=j;
if(h<=t)f[nw][i][j]=f[pw][i][Q[h]]+Q[h]-j;
}
}
else
for(int i=1;i<=n;++i)
{
h=1;t=0;
for(int j=1;j<=m;++j)
{
if(g[i][j]=='x'){h=1;t=0;continue;}
while(h<=t&&j-Q[h]>R[tt]-L[tt]+1)++h;
while(h<=t&&f[pw][i][Q[t]]-Q[t]<=f[pw][i][j]-j)--t;
Q[++t]=j;
if(h<=t)f[nw][i][j]=f[pw][i][Q[h]]+j-Q[h];
}
}
}
for(int i=1;i<=n;++i)
for(int j=1;j<=m;++j)
ans=max(ans,f[K&1][i][j]);
printf("%d\n",ans);
return 0;
}

【BZOJ1499】瑰丽华尔兹(动态规划)的更多相关文章

  1. Vijos1834 NOI2005 瑰丽华尔兹 动态规划 单调双端队列优化

    设dp[t][x][y]表示处理完前t个时间段,钢琴停留在(x,y)处,最多可以走多少个格子 转移时只需逆着当前倾斜的方向统计len个格子(len为时间区间的长度,len=t-s+1),如果遇到障碍就 ...

  2. 洛谷2254 BZOJ1499 瑰丽华尔兹题解

    洛谷链接 BZ链接 一个很容易想到的做法就是用f[i][j][t]表示t时刻在i,j处的可以滑动的最大值 f[i][j][t]=max(f[i][j][t-1],f[*i][*j][t-1]),这样大 ...

  3. 【BZOJ1499】【NOI2005】瑰丽华尔兹(动态规划)

    [BZOJ1499]瑰丽华尔兹(动态规划) 题面 BZOJ 题解 先写部分分 设\(f[t][i][j]\)表示当前在\(t\)时刻,位置在\(i,j\)时走的最多的步数 这样子每一步要么停要么走 时 ...

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

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

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

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

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

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

  7. DP+单调队列 codevs 1748 瑰丽华尔兹(还不是很懂具体的代码实现)

    codevs 1748 瑰丽华尔兹 2005年NOI全国竞赛  时间限制: 1 s  空间限制: 128000 KB  题目等级 : 大师 Master 题解       题目描述 Descripti ...

  8. NOI2005瑰丽华尔兹

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

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

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

随机推荐

  1. 阶段小项目1:循环间隔1秒lcd显示红绿蓝

    #include<stdlib.h>#include<stdio.h>#include<string.h>#include<error.h>#inclu ...

  2. Promise对象的简单用法

    要了解一个东西,首先要从,它是什么.用来做什么以及怎么取用它这三个方面来了解. 首先,promise是什么? 我们来参考一下MDN对它的定义: Promise 对象用于一个异步操作的最终完成(或失败) ...

  3. redis —主从&&集群(CLUSTER)

    REDIS主从配置 为了节省资源,本实验在一台机器进行.即,在一台机器上启动两个端口,模拟两台机器. 机器准备: [root@adailinux ~]# cp /etc/redis.conf /etc ...

  4. ubuntu:通过封装验证码类库一步步安装php的gd扩展

    我相信很多人的lamp环境都是直接复制一堆参数安装进去的,这里有可能成功,也有可能失败,如果是新手,估计要碰到各种错误,就算安装成功,也未必知道那些参数是干嘛的,反正装进去能用就行. 我当初开始的时候 ...

  5. C/C++调试分析工具

    一.静态分析工具 cppcheck cppcheck主要用于对C/C++源代码进行分析检查的一个开源工具,可以用来检测未使用的变量.越界访问.内存泄漏等问题. 使用方法 cppcheck --enab ...

  6. 排序算法(Java实现)

    这几天一直在看严蔚敏老师的那本<数据结构>那本书.之前第一次学懵懵逼逼,当再次看的时候,发觉写的是非常详细,非常的好. 那就把相关的排序算法用我熟悉的Java语言记录下来了.以下排序算法是 ...

  7. SpringMvc自动装配@Controller无效

    1.问题原因:SpringMvc驱动器没有扫描该Controller层 虽然配置了 <!-- 启用spring mvc 注解 --> <context:annotation-conf ...

  8. SpringMvc笔记-对RESTFUL风格的配置

    1.@RequestMapping注解可以使用如下参数: 1,params:例如params={'username',"age!=100"}表示需要usernmame并且age 属 ...

  9. 在Angular中利用trackBy来提升性能

    在Angular的模板中遍历一个集合(collection)的时候你会这样写: <ul> <li *ngFor="let item of collection"& ...

  10. hdu5296 01字典树

    根据二进制建一棵01字典树,每个节点的答案等于左节点0的个数 * 右节点1的个数 * 2,遍历整棵树就能得到答案. AC代码: #include<cstdio> using namespa ...