[JZOJ3507] 游乐场

来源:互联网 发布:大学生交通事故数据 编辑:程序博客网 时间:2024/04/28 06:27

Description

今天是个好日子,小A和他的小伙伴们一起去逛游乐园。这时,游乐园中忽然出现了一个伪装的吸血鬼,小A和他的小伙伴们都惊呆了!小伙伴们马上跑向了游乐园的四面八方。当“吸血鬼”回家吃饭的时候,小A才发现他已经和他的小伙伴们走散了。小A是个路痴,所以他只好站在原地等小伙伴们回来。

我们可以将游乐园视为一个N行M列的矩形,最上面一行为第1行,最左边一列为第1列。每个小伙伴手里都有一张神奇的地图,地图中对应着游乐园的每行每列都有一个写着0-9中某个数字的路标。小A的K位小伙伴们每一秒都会依次进行以下行动:

  1. 读取他所在的位置上的路标X;

  2. 顺时针旋转90度X次;

  3. 如果他面对游乐园外,那就他会再转180度;

  4. 移动到他面对的位置。

小A的视力很糟糕。只有当所有的小伙伴都同时出现在他所在的位置时,他才能和他的小伙伴们团聚。小A等得很心急,所以他求助于你。请你告诉他,他和小伙伴们团聚所需要的时间。

对于100%的数据,3<=N, M<=50,1<=K<=5如果小A和他的小伙伴们能够团聚,团聚的总秒数小于10^18。

Solution

显然我们需要找循环节。

首先将每个点拆成四个状态,从不同方向进入。
先考虑在环内。
根据环中到达小A点的状态,可以列出方程组。
T=X+kY
X表示第一次在环中到这个状态的时间,Y表示环的长度。
那就是

TX(modY)

对于同一个人可能在环中从不同方向经过目标点,那么就枚举选哪一个。
现在要解最小的T
观察
TX1(modY1)

TX2(modY2)

合并后的式子就是

TA(modlcm(Y1,Y2))

完全可以暴力解,枚举k1(Y的系数),判断是否符合下面的式子。
一条条合并,到最后的A就是答案,因为我们要T最小。

然后再看环以外的,用个标记桶存起来,特判即可。

Code

#include <cstdio>#include <cstdlib>#include <cstring>#include <cmath>#include <algorithm>#include <iostream>#define fo(i,a,b) for(int i=a;i<=b;i++)#define fod(i,a,b) for(int i=a;i>=b;i--)#define LL long long#define N 55 using namespace std;int map[N][N],n,m,l,xt,yt,fr[6][3],fx[4][2]={{-1,0},{0,1},{1,0},{0,-1}},d[9][2],rx,bz[4*N*N],num[6],b1[N][N][4];LL fc1[6][2],ans,fc[6][5][2],ti,s[4][2];LL gcd(LL x,LL y){    LL r=y;    while(r!=0) r=x%y,x=y,y=r;    return x;}void find(int x,int y,int f,int dis){    while(b1[x][y][f]<2)    {        b1[x][y][f]++;        if(x==xt&&y==yt)        {            d[++d[0][0]][0]=dis;            d[d[0][0]][1]=f;            if(s[f][0]==0) s[f][0]=dis;            else if(s[f][1]==0)             {                if(rx==-1) rx=d[0][0];                s[f][1]=dis;                ti=s[f][1]-s[f][0];            }            else             {                d[0][0]--;                return;            }        }        f=(f+map[x][y])%4;        LL x2=x+fx[f][0],y2=y+fx[f][1];        if(x2<1||x2>n||y2<1||y2>m) f=(f+2)%4;        x2=x+fx[f][0],y2=y+fx[f][1];        x=x2,y=y2;        dis++;    }}void dfs(int i){    if(i>l)     {        if(fc1[l][1]<ans||ans==-1) ans=fc1[l][1];        return;    }    fo(j,1,num[i])    {        fc1[i][0]=fc[i][j][0];        fc1[i][1]=fc[i][j][1];        if(i==1)         {            dfs(i+1);            continue;        }        LL p=fc1[i][0]/gcd(fc1[i][0],fc1[i-1][0]),v=fc1[i-1][1];        if(v%fc1[i][0]==fc1[i][1]%fc1[i][0]&&v>=fc1[i][1]) fc1[i][0]=p*fc1[i-1][0],fc1[i][1]=v,dfs(i+1);        else        {        fo(k,1,p)         {            v+=fc1[i-1][0];            if(v%fc1[i][0]==fc1[i][1]%fc1[i][0]&&v>=fc1[i][1]) break;        }        if(v%fc1[i][0]==fc1[i][1]%fc1[i][0]&&v>=fc1[i][1]) fc1[i][0]=p*fc1[i-1][0],fc1[i][1]=v,dfs(i+1);        }    }}int main(){    cin>>n>>m>>l;    cin>>xt>>yt;    fo(i,1,4*N-1) bz[i]=1;    bool pd=0;    fo(i,1,l)     {        scanf("%d%d",&fr[i][0],&fr[i][1]);        char ch;        scanf("%c",&ch);        scanf("%c",&ch);        if(ch=='U') fr[i][2]=0;        if(ch=='R') fr[i][2]=1;        if(ch=='D') fr[i][2]=2;        if(ch=='L') fr[i][2]=3;        fo(j,1,n)        {            scanf("\n");            fo(k,1,m)            {                char ch;                scanf("%c",&ch);                map[j][k]=(ch-'0')%4;            }        }        memset(s,0,sizeof(s));        memset(d,255,sizeof(d));        d[0][0]=0;        rx=-1;        memset(b1,0,sizeof(b1));        find(fr[i][0],fr[i][1],fr[i][2],1);        if(d[0][0]==0)        {            printf("-1\n");            return 0;        }        if(rx==-1)         {            fo(i,1,d[0][0]) bz[d[i][0]]++;            pd=1;        }        else        {            fo(j,1,d[0][0]) bz[d[j][0]]++;            LL p=d[d[0][0]][0]+ti;            fo(j,rx,d[0][0])            {                num[i]++;                while(p<=4*n*m)                {                    bz[p]++;                    p+=ti;                }                fc[i][num[i]][0]=ti;                fc[i][num[i]][1]=s[d[j][1]][0];            }        }    }    int fs=-1;    fo(i,1,4*n*m)    {        if(bz[i]==l&&fs!=-1)        {            fs=i;            break;        }    }    if(pd) printf("%d\n",fs);    else    {        ans=-1;        dfs(1);        if(fs=-1||ans<fs) printf("%lld\n",ans);        else printf("%d\n",fs);    }}
0 0
原创粉丝点击