zoukankan      html  css  js  c++  java
  • BZOJ1499: [NOI2005]瑰丽华尔兹

    【传送门:BZOJ1499


    简要题意:

      有一个字符矩阵,'.'表示能走,'x'表示不能走,给出起点的坐标,起点有一座钢琴,每单位时间可以移动一格,共有k个时间段,然后再给出每个时间段起始时间和结束时间,以及当前时间段能够移动的方向。而在某个时间,可以控制钢琴不动,钢琴不能走到'x'而且不能走出矩阵

      求出钢琴最多能走多少格


    题解:

      一眼DP题

      设f[t][i][j]表示第t时间走到(i,j)最多能走的格数,f[t][i][j]=max(f[t-1][i][j],f[t-1][i-dx[i]][j-dy[i]]+1),时间复杂度O(nmT),超时

      我们重新搞DP方程,设f[k][i][j]表示第k时间段走到(i,j)最多能走的格数,f[k][i][j]=max(f[k][i][j],f[k-1][i-dx[i]*c][j-dy[i]*c]+c),c为第k-1时间段走多长时间

      因为每个时间段都是对于一行或者一列进行操作的,所以我们可以分成四种情况来单调队列

      这样子时间复杂度就是O(nmk)

      还要提的一点是,最好用滚动数组,优化一下空间


    参考代码:

    #include<cstdio>
    #include<cstring>
    #include<cstdlib>
    #include<algorithm>
    #include<cmath>
    using namespace std;
    char st[210][210];
    struct node
    {
        int d,t;
    }T[210];
    int f[2][210][210];
    int list[210];
    int main()
    {
        int n,m,x,y,k;
        scanf("%d%d%d%d%d",&n,&m,&x,&y,&k);
        for(int i=1;i<=n;i++) scanf("%s",st[i]+1);
        for(int i=1;i<=k;i++)
        {
            int l,r;
            scanf("%d%d%d",&l,&r,&T[i].t);
            T[i].d=r-l+1;
        }
        memset(f,-63,sizeof(f));
        f[0][x][y]=0;
        int now=0,last=1,head,tail;
        for(int K=1;K<=k;K++)
        {
            now^=1;last^=1;
            if(T[K].t==1)
            {
                for(int j=1;j<=m;j++)
                {
                    head=1;tail=0;
                    for(int i=n;i>=1;i--)
                    {
                        if(st[i][j]=='x') head=1,tail=0;
                        while(head<=tail&&list[head]-i>T[K].d) head++;
                        if(head<=tail) f[now][i][j]=f[last][list[head]][j]+list[head]-i;
                        while(head<=tail&&f[last][i][j]>f[last][list[tail]][j]+list[tail]-i) tail--;
                        list[++tail]=i;
                        f[now][i][j]=max(f[now][i][j],f[last][i][j]);
                    }
                }
            }
            if(T[K].t==2)
            {
                for(int j=1;j<=m;j++)
                {
                    head=1;tail=0;
                    for(int i=1;i<=n;i++)
                    {
                        if(st[i][j]=='x') head=1,tail=0;
                        while(head<=tail&&i-list[head]>T[K].d) head++;
                        if(head<=tail) f[now][i][j]=f[last][list[head]][j]+i-list[head];
                        while(head<=tail&&f[last][i][j]>f[last][list[tail]][j]+i-list[tail]) tail--;
                        list[++tail]=i;
                        f[now][i][j]=max(f[now][i][j],f[last][i][j]);
                    }
                }
            }
            if(T[K].t==3)
            {
                for(int i=1;i<=n;i++)
                {
                    head=1;tail=0;
                    for(int j=m;j>=1;j--)
                    {
                        if(st[i][j]=='x') head=1,tail=0;
                        while(head<=tail&&list[head]-j>T[K].d) head++;
                        if(head<=tail) f[now][i][j]=f[last][i][list[head]]+list[head]-j;
                        while(head<=tail&&f[last][i][j]>f[last][i][list[tail]]+list[tail]-j) tail--;
                        list[++tail]=j;
                        f[now][i][j]=max(f[now][i][j],f[last][i][j]);
                    }
                }
            }
            if(T[K].t==4)
            {
                for(int i=1;i<=n;i++)
                {
                    head=1;tail=0;
                    for(int j=1;j<=m;j++)
                    {
                        if(st[i][j]=='x') head=1,tail=0;
                        while(head<=tail&&j-list[head]>T[K].d) head++;
                        if(head<=tail) f[now][i][j]=f[last][i][list[head]]+j-list[head];
                        while(head<=tail&&f[last][i][j]>f[last][i][list[tail]]+j-list[tail]) tail--;
                        list[++tail]=j;
                        f[now][i][j]=max(f[now][i][j],f[last][i][j]);
                    }
                }
            }
        }
        int ans=0;
        for(int i=1;i<=n;i++) for(int j=1;j<=m;j++) ans=max(f[now][i][j],ans);
        printf("%d
    ",ans);
        return 0;
    }

     

  • 相关阅读:
    48. Rotate Image
    47. Permutations II
    46. Permutations
    45. Jump Game II
    44. Wildcard Matching
    43. Multiply Strings
    42. Trapping Rain Water
    41. First Missing Positive
    40. Combination Sum II
    39. Combination Sum
  • 原文地址:https://www.cnblogs.com/Never-mind/p/8528116.html
Copyright © 2011-2022 走看看