zoukankan      html  css  js  c++  java
  • 洛谷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]),这样大力转移

    只不过会TLE+MLE

    所以我们要进行一下优化

    f[i][j][k]表示在第k个时间段在i,j处的可以滑动的最大值

    f[i][j][k]=max(f[*i][*j][k-1]+dis(i,j,*i,*j,f[i][j][k-1])

    //*i,*j表示上一个合理的位置

    注意到我们的i,与*i,以及j与*j一定有一个相等,即它们在同一行或者同一列

    所以我们可以根据滑动的路径一行一行或者一列一列进行转移

    而这个位置的可以转移来的位置即是它向前len长度的之内的位置

    这与滑动窗口很类似,可以用单调队列来维护max(f[*i][*j][k-1])

    然后在考虑障碍,我们发现一旦遇到障碍,之前的答案都不能转移过来

    所以在有障碍是清空队列就好了

    还有一个常规的优化,就是f[i][j][k]仅与f[i][j][k-1]有关,所以可以利用滚动数组进行优化

    # include<iostream>
    # include<cstdio>
    # include<cmath>
    # include<cstring>
    # include<algorithm>
    using namespace std;
    const int mn = 205;
    const int dx[]={0,-1,1,0,0};
    const int dy[]={0,0,0,-1,1};
    struct node{int val,pos;};
    node q[mn];
    node make_node(int x,int y)
    {
        node tmp;tmp.val=x,tmp.pos=y;
        return tmp;
    }
    int n,m,sx,sy,k;
    int dp[mn][mn],ans,d;
    char s[mn];
    bool vis[mn][mn];
    void work(int x,int y,int len)
    {
        int tail=1,head=0;
        for(int i=1;x>=1 && x<=n && y>=1 && y<=m;i++,x+=dx[d],y+=dy[d])
        {
            if(!vis[x][y]) tail=1,head=0;
            else {
               while(tail<=head && q[head].val+i-q[head].pos<=dp[x][y]) head--;
               q[++head] = make_node(dp[x][y],i);//dp[x][y]实际上是dx[x][y][k-1]
           //BZOJ不支持c++11,写成q[++head]=node{dp[x][y],i}会CE
    while(tail<=head && q[head].pos-q[tail].pos>len) tail++; dp[x][y] = q[tail].val+i-q[tail].pos;//现在dp[x][y]才是dp[x][y][k] ans=max(ans,dp[x][y]); } } } int main() { int x,y,z; scanf("%d%d%d%d%d",&n,&m,&sx,&sy,&k); for(int i=1;i<=n;i++) { scanf("%s",s+1); for(int j=1;j<=m;j++) if(s[j]=='.') vis[i][j]=1; else vis[i][j]=0; } memset(dp,0xf3,sizeof(dp)); dp[sx][sy]=0; for(int i=1;i<=k;i++) { scanf("%d%d%d",&x,&y,&d); if(d==1) for(int j=1;j<=m;j++) work(n,j,y-x+1); if(d==2) for(int j=1;j<=m;j++) work(1,j,y-x+1); if(d==3) for(int j=1;j<=n;j++) work(j,m,y-x+1); if(d==4) for(int j=1;j<=n;j++) work(j,1,y-x+1); } printf("%d",ans); return 0; }
  • 相关阅读:
    Swizzling的使用
    Kubelet
    Windows 下 LaTeX 手动安装宏包(package)以及生成帮助文档的整套流程
    Leetcode-Day Three
    吴裕雄--天生自然Linux操作系统:Linux 用户和用户组管理
    吴裕雄--天生自然Linux操作系统:Linux 文件与目录管理
    吴裕雄--天生自然Linux操作系统:Linux 文件基本属性
    吴裕雄--天生自然Linux操作系统:Linux 远程登录
    吴裕雄--天生自然Linux操作系统:Linux 忘记密码解决方法
    吴裕雄--天生自然Linux操作系统:Linux 系统目录结构
  • 原文地址:https://www.cnblogs.com/logeadd/p/9540285.html
Copyright © 2011-2022 走看看