bzoj1499: [NOI2005]瑰丽华尔兹

dp.

首先我们可以看到每个时间段只能往一个方向转移最多t步(t为时间段的长度),所以我们可以按时间段dp。因为这个前后值互不影响,也不用占用这一维空间就可以省去。

然后每个时间段内是一列一列(行) 进行递推。 如果朴素枚举是O(n^2)时间无法承受。所以每列(行)用一个单调队列维护dp,队首放着移动距离最大可以到达的点,这样复杂度就降到了O(n)。每次要递推n列(行)。所以总复杂度为O(k*n^2)。

#include<cstdio>
#include<algorithm>
#include<cstring>
using namespace std;
#define ans first
#define pos second
const int maxn = 200 + 10;
const int dx[]={-1,1,0,0},dy[]={0,0,-1,1};
pair<int,int> q[maxn],tmp;
int f[maxn][maxn];
char g[maxn][maxn];
int n,m,k,x,y,l,r,res;

inline bool inrange(int x,int y) {
    return x>=1 && x<=n && y>=1 && y<=m;
}

void solve(int x,int y,int d,int len) {
    l=r=0;
    for(int i=0;inrange(x,y);i++,x+=dx[d],y+=dy[d]) {
        if(g[x][y]==‘x‘) l=r=0;
        else {
            tmp.ans=f[x][y]; tmp.pos=i;
            while(l<r && q[r-1].ans+(i-q[r-1].pos)<=tmp.ans) r--;
            q[r++]=tmp;
            while(l<r && (i-q[l].pos)>len) l++;
            f[x][y]=q[l].ans+(i-q[l].pos);
            res=max(res,f[x][y]);
        }
    }
}

int main() {
    scanf("%d%d%d%d%d",&n,&m,&x,&y,&k);
    for(int i=1;i<=n;i++) scanf("%s",g[i]+1);

    memset(f,0x80,sizeof(f)); f[x][y]=0;
    for(int i=1,s,e,d,len;i<=k;i++) {
        scanf("%d%d%d",&s,&e,&d),len=e-s+1;
        if(d==1) for(int j=1;j<=m;j++) solve(n,j,0,len);
        else if(d==2) for(int j=1;j<=m;j++) solve(1,j,1,len);
        else if(d==3) for(int j=1;j<=n;j++) solve(j,m,2,len);
        else for(int j=1;j<=n;j++) solve(j,1,3,len);
    }
    printf("%d\n",res);
    return 0;
}
时间: 2024-08-26 00:40:02

bzoj1499: [NOI2005]瑰丽华尔兹的相关文章

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

1499: [NOI2005]瑰丽华尔兹 Time Limit: 3 Sec  Memory Limit: 64 MBSubmit: 1802  Solved: 1097[Submit][Status][Discuss] Description 你跳过华尔兹吗?当音乐响起,当你随着旋律滑动舞步,是不是有一种漫步仙境的惬意?众所周知,跳华尔兹时,最重要的是有好的音乐.但是很少有几个人知道,世界上最伟大的钢琴家一生都漂泊在大海上,他的名字叫丹尼•布德曼•T.D.•柠檬•1900,朋友们都叫他1900

[BZOJ1499][NOI2005]瑰丽华尔兹 dp+单调队列

1499: [NOI2005]瑰丽华尔兹 Time Limit: 3 Sec  Memory Limit: 64 MBSubmit: 1810  Solved: 1102[Submit][Status][Discuss] Description 你跳过华尔兹吗?当音乐响起,当你随着旋律滑动舞步,是不是有一种漫步仙境的惬意?众所周知,跳华尔兹时,最重要的是有好的音乐.但是很少有几个人知道,世界上最伟大的钢琴家一生都漂泊在大海上,他的名字叫丹尼?布德曼?T.D.?柠檬?1900,朋友们都叫他1900

BZOJ1499 [NOI2005]瑰丽华尔兹 【单调队列优化dp】

题目 你跳过华尔兹吗?当音乐响起,当你随着旋律滑动舞步,是不是有一种漫步仙境的惬意?众所周知,跳华尔兹时,最重要的是有好的音乐.但是很少有几个人知道,世界上最伟大的钢琴家一生都漂泊在大海上,他的名字叫丹尼?布德曼?T.D.?柠檬?1900,朋友们都叫他1900. 1900在20世纪的第一年出生在往返于欧美的邮轮弗吉尼亚号上,很不幸他刚出生就被抛弃了,成了孤儿.1900孤独的成长在弗吉尼亚号上,从未离开过这个摇晃的世界.也许是对他命运的补偿,上帝派可爱的小天使艾米丽照顾他.可能是天使的点化,190

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

[BZOJ1499][NOI2005]瑰丽华尔兹 Description 你跳过华尔兹吗?当音乐响起,当你随着旋律滑动舞步,是不是有一种漫步仙境的惬意?众所周知,跳华尔兹时,最重要的是有好的音乐.但是很少有几个人知道,世界上最伟大的钢琴家一生都漂泊在大海上,他的名字叫丹尼•布德曼•T.D.•柠檬•1900,朋友们都叫他1900. 1900在20世纪的第一年出生在往返于欧美的邮轮弗吉尼亚号上,很不幸他刚出生就被抛弃了,成了孤儿.1900孤独的成长在弗吉尼亚号上,从未离开过这个摇晃的世界.也许是对他

NOI2005瑰丽华尔兹

1499: [NOI2005]瑰丽华尔兹 Time Limit: 3 Sec  Memory Limit: 64 MBSubmit: 893  Solved: 508[Submit][Status] Description 你跳过华尔兹吗?当音乐响起,当你随着旋律滑动舞步,是不是有一种漫步仙境的惬意?众所周知,跳华尔兹时,最重要的是有好的音乐.但是很少有几个人知道,世界上最伟大的钢琴家一生都漂泊在大海上,他的名字叫丹尼•布德曼•T.D.•柠檬•1900,朋友们都叫他1900. 1900在20世纪

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

设dp[t][x][y]表示处理完前t个时间段,钢琴停留在(x,y)处,最多可以走多少个格子 转移时只需逆着当前倾斜的方向统计len个格子(len为时间区间的长度,len=t-s+1),如果遇到障碍就中断 转移过程可以用单调非递增的双端队列优化 1 #include <cstdio> 2 #include <cstring> 3 #include <algorithm> 4 5 const int maxN=202; 6 const int inf=0x3f3f3f3f

BZOJ 1499 NOI2005 瑰丽华尔兹 单调队列

题目大意:给定一个m*n的地图,一些点有障碍物,钢琴初始在一个点,每个时间段可以选择向给定的方向移动一段距离,求最长路径长 朴素DP的话,我们有T个时间段,每个时间段有m*n个点,n个时间,一定会超时 考虑到一个时间段所有的更新操作都是相同的,我们可以考虑单调队列优化 设队尾为(x,y),新插入的点为(x',y'),那么当Distance( (x,y) , (x',y') ) <= f[x'][y'] - f[x][y]时,(x,y)可被删掉 四遍单调队列即可 O(T*m*n) #include

【DP】【单调队列】【NOI2005】瑰丽华尔兹

340. [NOI2005] 瑰丽华尔兹 ★★★ 输入文件:adv1900.in 输出文件:adv1900.out 简单对比 时间限制:1 s 内存限制:128 MB [任务描述] 你跳过华尔兹吗?当音乐响起,当你随着旋律滑动舞步,是不是有一种漫步仙境的惬意?众所周知,跳华尔兹时,最重要的是有好的音乐.但是很少有几个人知道,世界上最伟大的钢琴家一生都漂泊在大海上,他的名字叫丹尼?布德曼?T.D.?柠檬?1900,朋友们都叫他1900. 1900出生于20世纪的第一年出生在往返于欧美的邮轮弗吉尼亚

wikioi-1748 瑰丽华尔兹 -单调队列优化DP

根据题意,很明显可以推出DP方程. 假如只考虑向左的方向: dp[t][i][j]:  第t个时间段末滑行到i,j最长滑行的距离. dp[t][i][j]=dp[t-1][i][1..k]+(j-k)=dp[t-1][i][1..k]-k+j(k<=j)很明显,可以使用单调队列优化. 最终时间复杂度为O(n*m*k) #include<stdio.h> #include<string.h> #include<algorithm> #include<iostr