LOJ6388:[THUPC2018]赛艇——题解

https://loj.ac/problem/6388

如果你做过BZOJ5217:[Lydsy2017省队十连测]航海舰队的话,那么恭喜你,这道题就是大水题。

如果你做过BZOJ4259:残缺的字符串的话,那么基本的字符串匹配FFT也是能想到的。

如果没做过的话,很抱歉,没有一定的套路的话这道题很难想(而对于我这样的蒟蒻来说就是没法想。)

将行走路线看做一个地图b,走过的路为1,没走的为0.

于是可以变成这张地图可以与原地图a匹配多少次(匹配成功在于两张图的1不能重叠。)

按照BZOJ5217的套路,将二维压成一维,就变成了对于一个下标为p的点,不满足a[p+i]=1且b[i]=1。

于是有f[i]=sigma(a[i+j]*b[j])=0,将a数组颠倒得f[i]=sigma(a[n*m-i-j]*b[j])=0是卷积,可以FFT运算。

最后统计f[i]=0的个数即可。

#include<map>
#include<cmath>
#include<stack>
#include<queue>
#include<cstdio>
#include<cctype>
#include<vector>
#include<cstdlib>
#include<cstring>
#include<iostream>
#include<algorithm>
using namespace std;
typedef double dl;
const dl pi=acos(-1.0);
const dl eps=0.5;
const int M=1505;
const int N=M*M*8;
const int K=5e6+5;
struct complex{
    dl x,y;
    complex(dl xx=0,dl yy=0){
    x=xx;y=yy;
    }
    complex operator +(const complex &b)const{
    return complex(x+b.x,y+b.y);
    }
    complex operator -(const complex &b)const{
    return complex(x-b.x,y-b.y);
    }
    complex operator *(const complex &b)const{
    return complex(x*b.x-y*b.y,x*b.y+y*b.x);
    }
};
void FFT(complex a[],int n,int on){
    for(int i=1,j=n>>1;i<n-1;i++){
    if(i<j)swap(a[i],a[j]);
    int k=n>>1;
    while(j>=k){j-=k;k>>=1;}
    if(j<k)j+=k;
    }
    for(int i=2;i<=n;i<<=1){
    complex res(cos(-2*on*pi/i),sin(-2*on*pi/i));
    for(int j=0;j<n;j+=i){
        complex w(1,0);
        for(int k=j;k<j+i/2;k++){
        complex u=a[k],t=w*a[k+i/2];
        a[k]=u+t;a[k+i/2]=u-t;
        w=w*res;
        }
    }
    }
    if(on==-1)
    for(int i=0;i<n;i++)a[i].x/=n;
}
bool tmp[M*2+10][M*2+10];
int n,m,k;
char mp[M][M],s[K];
complex a[N],b[N];
int main(){
    scanf("%d%d%d",&n,&m,&k);
    for(int i=1;i<=n;i++)scanf("%s",mp[i]+1);

    for(int i=1;i<=n;i++)
    for(int j=1;j<=m;j++)
        if(mp[i][j]=='1')a[n*m-(i-1)*m-j]=complex(1,0);
    
    scanf("%s",s);
    int x=n,y=m;
    int x1=n,y1=m,x2=n,y2=m;
    tmp[x][y]=1;
    for(int i=0;i<k;i++){
        if(s[i]=='w')x--;
    if(s[i]=='a')y--;
        if(s[i]=='s')x++;
        if(s[i]=='d')y++;
    tmp[x][y]=1;
    x1=min(x1,x),y1=min(y1,y),x2=max(x2,x),y2=max(y2,y);
    }
    for(int i=x1;i<=x2;i++)
    for(int j=y1;j<=y2;j++)
        if(tmp[i][j])b[(i-x1)*m+j-y1]=complex(1,0);

    int len=1;
    while(len<n*m)len<<=1;
    FFT(a,len,1);FFT(b,len,1);
    for(int i=0;i<len;i++)a[i]=a[i]*b[i];
    FFT(a,len,-1);

    int ans=0;
    for(int i=1;i<=n-(x2-x1);i++)
    for(int j=1;j<=m-(y2-y1);j++)
        if(a[n*m-(i-1)*m-j].x<eps)ans++;
    printf("%d\n",ans);
    return 0;
}

+++++++++++++++++++++++++++++++++++++++++++

 +本文作者:luyouqi233。               +

 +欢迎访问我的博客:http://www.cnblogs.com/luyouqi233/+

+++++++++++++++++++++++++++++++++++++++++++

posted @ 2018-06-10 20:17  luyouqi233  阅读(234)  评论(0编辑  收藏  举报