zoukankan      html  css  js  c++  java
  • bzoj4624: 农场种植

    Description

    农夫约翰想要在一片巨大的土地上建造一个新的农场。 这块土地被抽象为个 R*C 的矩阵。土地中的每个方格都可
    以用来生产一种食物:谷物(G)或者是牲畜(L)。下面是一个 R 为 5,C 为 8 的土地的样例:
      12345678
    1 GLGGLGLG
    2 GGLGGLGL
    3 GGLLLGGG
    4 LLGLLGLG
    5 LGGGLGLL
    农夫约翰已经有一套设计好的他想要建造的农场的蓝图。 每一个蓝图被抽象为一个 H*W 的矩阵,其中 H≤R,W≤
    C。蓝图中的每个方格表示着农夫约翰想要生产的食物,谷物(G)或是牲畜(L)。下面是一个 H=2,W=3 的蓝图的样
    例。
      123
    1 GLL
    2 LGG
    使用这个蓝图,农夫约翰可以在土地上的某个位置建立起实际的农场。这个农场的位置可以用它的左上角的位置来
    代表, 比如这个农场被建立在土地上的(r,c)这个位置,这个农场必须整个都建立在这块土地中(也就是说 r + H
     ≤ R 并且 c + W ≤ C) 。如果在土地上的位置(r + i, c + j)的食物种类和蓝图里的位置(i + 1, j + 1)的食
    物种类相同(其中 0 ≤ i<H,0 ≤ j<W) ,那么就能出产食物。农夫约翰想要找到这样的农场位置,使得他可以
    出产最多的食物(即谷物的格数+牲畜的格数) 。如果有多于一个可能的解,输出最上方的一个,如果仍然有多于
    一个可能的解,就输出最作坊的一个。比如对于上面给出的土地和蓝图的样例,最佳的农场位置是(1, 3),这是最
    左上方的一个可行的农场,如下图所示:
      12345678
    1 GLGGLGLG
    2 GGLGGLGL
    3 GGLLLGGG
    4 LLGLLGLG
    5 LGGGLGLL
    通过在(1, 3)位置建立农场,农夫约翰可以生产出 5 格的粮食,3 格谷物和2 格牲畜,具体来说,是第一行的一
    格谷物和一个牲畜,第二行的一格牲畜和两格谷物。注意位置(2, 5)和位置(3, 2)同样能生产出 5 格谷物,但是
    农夫约翰需要的是最靠上中的最靠左的。 在除此以外的任何位置放置农场都只能生产出少于5 格的食物。

    Input

    输入数据中只有一组土地,第一行包含了两个整数 R 和 C,其中 0 <R,C ≤500,紧接着是 R 行每行包含 C 个字
    符来描述这片土地,接下来有一个整数 B,满足 0 <B ≤ 5,表示农夫约翰拥有的蓝图的数量,接下来是 B 个蓝
    图,每个蓝图都以包含两个整数 H 和 W 的一行开头,其中 0 <H ≤ R 并且 0 <W ≤ C,紧接着是 H 行,每行 W
     个字母来描述这个蓝图。对于每个蓝图,在一行中输出"Case #X: Y"(没有引号) ,X 是蓝图编号,从 1 开始
    ,Y 是一组用空格隔开的四个整数组成的输出,前两个整数表示最好的建造农场的位置,接下来两个整数分别表示
    可以生产的谷物和牲畜的格数。
    R,C ≤ 500,B≤5,H≤R,W≤C

    Output

    对于每个蓝图,在一行中输出"Case #X: Y"(没有引号) ,X 是蓝图编号,从 1 开始,Y 是一组用空格隔开的四
    个整数组成的输出,前两个整数表示最好的建造农场的位置,接下来两个整数分别表示可以生产的谷物和牲畜的格
    数。

    这题可以把矩阵展开成01串S,蓝图用通配符从h*w补齐到R*C并转为带通配符的01串T

    将蓝图对应的串翻转,G改为1,L改成-1,通配符改成0

    此时可以发现两串的卷积代表了从每个位置开始匹配,S与T的相同字符数-不同字符数,通配符则被忽略

    卷积最大且最左的合法位置即为答案

    用fft优化卷积可以做到O(BRClog(RC))

    #include<cstdio>
    #include<cmath>
    const int N0=524288;
    int N,P;
    const double pi=3.14159265358979323846;
    struct C{
        double a,b;
        C(double x=0,double y=0):a(x),b(y){}
        C operator+(C x){return C(a+x.a,b+x.b);}
        C operator-(C x){return C(a-x.a,b-x.b);}
        C operator*(C x){return C(a*x.a-b*x.b,a*x.b+b*x.a);}
    }A[N0],B[N0],tmp;
    int rev[N0];
    void dft(C*a,int t){
        for(int i=0;i<N;i++)if(i>rev[i])tmp=a[i],a[i]=a[rev[i]],a[rev[i]]=tmp;
        for(int i=1;i<N;i<<=1){
            C w(cos(pi/i),t*sin(pi/i));
            for(int j=0;j<N;j+=i<<1){
                C e(1),*b=a+j,*c=b+i;
                for(int k=0;k<i;k++,e=e*w){
                    C x=b[k],y=e*c[k];
                    b[k]=x+y;c[k]=x-y;
                }
            }
        }
        if(t==-1)for(int i=0;i<N;i++)a[i].a/=N;
    }
    int r,c,T,h,w;
    char s[512][512],s2[512][512];
    int t[N0];
    void rs(char*s){
        int c=getchar();
        while(c!='G'&&c!='L')c=getchar();
        while(c=='G'||c=='L')*(s++)=c,c=getchar();
    }
    int main(){
        scanf("%d%d",&r,&c);
        for(int i=0;i<r;i++)rs(s[i]);
        for(N=2,P=0;N<=r*c*2+2;N<<=1,++P);
        for(int i=1;i<N;i++)rev[i]=rev[i>>1]>>1|(i&1)<<P;
        int l=r*c-1;
        scanf("%d",&T);
        for(int I=1;I<=T;I++){
            scanf("%d%d",&h,&w);
            for(int i=0;i<h;i++)rs(s2[i]);
            for(int i=0;i<r;i++)for(int j=0;j<c;j++)A[i*c+j]=C(s[i][j]=='G'?1:-1);
            for(int i=r*c;i<N;i++)A[i]=C();
            for(int i=0;i<N;i++)B[i]=C();
            for(int i=0;i<h;i++)for(int j=0;j<w;j++)B[l-i*c-j]=C(s2[i][j]=='G'?1:-1);
            dft(A,1);dft(B,1);
            for(int i=0;i<N;i++)A[i]=A[i]*B[i];
            dft(A,-1);
            for(int i=0;i<N-l;i++)t[i]=int(A[l+i].a+.5);
            int px=0,py=0,mx=0,t1=0,t2=0;
            for(int i=0;i<=r-h;i++)for(int j=0;j<=c-w;j++)if(t[i*c+j]>mx)mx=t[i*c+j],px=i,py=j;
            for(int i=0;i<h;i++)for(int j=0;j<w;j++)if(s[px+i][py+j]==s2[i][j]){
                if(s[px+i][py+j]=='G')++t1;
                else ++t2;
            }
            printf("Case #%d: %d %d %d %d
    ",I,px+1,py+1,t1,t2);
        }
        return 0;
    }
  • 相关阅读:
    Linux命令——getfacl、setfacl
    Linux命令——groups
    Linux命令——gdisk、fdisk、partprobe
    Linux命令——parted
    Linux命令——blkid
    Linux命令——chattr、lsattr
    Linux命令——od
    Linux命令——basename、dirname
    Linux命令——chgrp、chown、chmod
    Linux命令——pidof
  • 原文地址:https://www.cnblogs.com/ccz181078/p/5645013.html
Copyright © 2011-2022 走看看