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


    题目链接
    题解:
    首先,我们很容易得出dp方程。让f[i][j][k]表示在第k段时间里走到(i,j)这个位置的最长滑动距离。这里以向北滑动举例,设第段时间内最多能走l步,l=s[k]t[k]+1。则有f[i][j][k]=max(f[a][j][k1]+aj)(aj,alj)。于是我们就可以用一个单调队列维护f[a][j][k1]+a的最大值。
    其他四个方向同理,就是循环的顺序变一下而已。
    k这一维内存可以用滚动数组优化掉。注意把到不了的位置赋值为-inf,只有队头的最优值不为-inf才更新当前的位置。遇到障碍物,要把队列清空,因为之前的决策全部没用了,走不到当前位置。初始化时把除初始位置之外的都赋值为-inf。
    细节详见代码。

    #include<cstdio>
    const int N=205,inf=0x3f3f3f3f;
    int n,m,x,y,k,s,t,d,ans,head,tail,q[N],f[N][N],g[N][N];
    char str[N][N];
    void dp(int l){
        if(d==1){
            for(int j=1;j<=m;j++){
                head=1,tail=0;
                for(int i=n;i>=1;i--){
                    if(str[i][j]=='x'){
                        head=1,tail=0;
                        continue;
                    }
                    while(head<=tail&&q[head]-i>l){
                        head++;
                    }
                    while(head<=tail&&g[i][j]+i>g[q[tail]][j]+q[tail]){
                        tail--;
                    }
                    q[++tail]=i;
                    if(g[q[head]][j]!=-inf){
                        f[i][j]=g[q[head]][j]+q[head]-i;
                    }
                }
            }
        }else if(d==2){
            for(int j=1;j<=m;j++){
                head=1,tail=0;
                for(int i=1;i<=n;i++){
                    if(str[i][j]=='x'){
                        head=1,tail=0;
                        continue;
                    }
                    while(head<=tail&&i-q[head]>l){
                        head++;
                    }
                    while(head<=tail&&g[i][j]-i>g[q[tail]][j]-q[tail]){
                        tail--;
                    }
                    q[++tail]=i;
                    if(g[q[head]][j]!=-inf){
                        f[i][j]=g[q[head]][j]+i-q[head];
                    }
                }
            }
        }else if(d==3){
            for(int i=1;i<=n;i++){
                head=1,tail=0;
                for(int j=m;j>=1;j--){
                    if(str[i][j]=='x'){
                        head=1,tail=0;
                        continue;
                    }
                    while(head<=tail&&q[head]-j>l){
                        head++;
                    }
                    while(head<=tail&&g[i][j]+j>g[i][q[tail]]+q[tail]){
                        tail--;
                    }
                    q[++tail]=j;
                    if(g[i][q[head]]!=-inf){
                        f[i][j]=g[i][q[head]]+q[head]-j;
                    }
                }
            }
        }else{
            for(int i=1;i<=n;i++){
                head=1,tail=0;
                for(int j=1;j<=m;j++){
                    if(str[i][j]=='x'){
                        head=1,tail=0;
                        continue;
                    }
                    while(head<=tail&&j-q[head]>l){
                        head++;
                    }
                    while(head<=tail&&g[i][j]-j>g[i][q[tail]]-q[tail]){
                        tail--;
                    }
                    q[++tail]=j;
                    if(g[i][q[head]]!=-inf){
                        f[i][j]=g[i][q[head]]+j-q[head];
                    }
                }
            }
        }
        for(int i=1;i<=n;i++){
            for(int j=1;j<=m;j++){
                g[i][j]=f[i][j];
                if(f[i][j]>ans){
                    ans=f[i][j];
                }
            }
        }
    }
    int main(){
        scanf("%d%d%d%d%d",&n,&m,&x,&y,&k);
        for(int i=1;i<=n;i++){
            scanf("%s",str[i]+1);
            for(int j=1;j<=m;j++){
                f[i][j]=g[i][j]=-inf;
            }
        }
        f[x][y]=g[x][y]=0;
        for(int i=1;i<=k;i++){
            scanf("%d%d%d",&s,&t,&d);
            dp(t-s+1);
        }
        printf("%d
    ",ans);
        return 0;
    }
  • 相关阅读:
    JSTL和EL
    JSP
    Servlet基础知识
    JSON基础知识
    jQuery基础知识
    ajax基础知识
    索引实战
    反射
    设计模式
    JVM的异常处理
  • 原文地址:https://www.cnblogs.com/2016gdgzoi471/p/9476888.html
Copyright © 2020-2023  润新知