zoukankan      html  css  js  c++  java
  • bzoj1499 [NOI2005]瑰丽华尔兹——单调队列优化DP

    题目:https://www.lydsy.com/JudgeOnline/problem.php?id=1499

    朴素DP方程很好想,以右移为例,就是 f[i][x][y]=max(f[i][x][y],f[i-1][x][j]+y-j) ;

    每一行/列会用到一些相同的状态更新,所以可以用单调队列优化。

    代码如下:

    #include<iostream>
    #include<cstdio>
    #include<cstring>
    using namespace std;
    int const maxn=205,inf=0x3f3f3f3f;
    int n,m,K,st,ed,f[3][maxn][maxn],xx[5]={0,-1,1,0,0},yy[5]={0,0,0,-1,1},L,ans;
    char s[maxn][maxn];
    struct N{
        int pos,ans;
    }q[maxn];
    void dp(int x,int y,int d,int nw)
    {
        int h=1,t=0;N tmp;
        for(int i=0;x&&y&&x<=n&&y<=m;i++,x+=xx[d],y+=yy[d])//i为与原来的y的差距,注意不要与y搞混 
        {
            if(s[x][y]=='x')h=1,t=0;//h!=0
            tmp.pos=i;tmp.ans=f[nw^1][x][y];
            while(h<=t&&i-q[h].pos>L)h++;//i  //<=
            while(h<=t&&tmp.ans>=q[t].ans+i-q[t].pos)t--;//i
            q[++t]=tmp;
            if(h>t)f[nw][x][y]=-inf;//
            else f[nw][x][y]=q[h].ans+i-q[h].pos;
            ans=max(ans,f[nw][x][y]);
        }
    }
    int main()
    {
        scanf("%d%d%d%d%d",&n,&m,&st,&ed,&K);
        for(int i=1;i<=n;i++)cin>>s[i]+1;
        memset(f,-0x3f,sizeof f);
        f[0][st][ed]=0;
        int l,r,d,nw=0;
        while(K--)
        {
            nw^=1;
            scanf("%d%d%d",&l,&r,&d);
            L=r-l+1;
            if(d==1)for(int i=1;i<=m;i++)dp(n,i,d,nw);
            if(d==2)for(int i=1;i<=m;i++)dp(1,i,d,nw);
            if(d==3)for(int j=1;j<=n;j++)dp(j,m,d,nw);
            if(d==4)for(int j=1;j<=n;j++)dp(j,1,d,nw);
        }
        printf("%d",ans);
        return 0;
    }
  • 相关阅读:
    GO开发[一]:golang语言初探
    Python带参数的装饰器
    Python函数篇
    19. logging模块
    18. json模块
    17. os模块
    16. sys模块
    15. random模块
    14. 模块-time模块
    29. java面向对象项目
  • 原文地址:https://www.cnblogs.com/Zinn/p/9163485.html
Copyright © 2011-2022 走看看