Description
今天是个好日子,小A和他的小伙伴们一起去逛游乐园。这时,游乐园中忽然出现了一个伪装的吸血鬼,小A和他的小伙伴们都惊呆了!小伙伴们马上跑向了游乐园的四面八方。当“吸血鬼”回家吃饭的时候,小A才发现他已经和他的小伙伴们走散了。小A是个路痴,所以他只好站在原地等小伙伴们回来。
我们可以将游乐园视为一个N行M列的矩形,最上面一行为第1行,最左边一列为第1列。每个小伙伴手里都有一张神奇的地图,地图中对应着游乐园的每行每列都有一个写着0-9中某个数字的路标。小A的K位小伙伴们每一秒都会依次进行以下行动:
- 读取他所在的位置上的路标X;
- 顺时针旋转90度X次;
- 如果他面对游乐园外,那就他会再转180度;
- 移动到他面对的位置。
小A的视力很糟糕。只有当所有的小伙伴都同时出现在他所在的位置时,他才能和他的小伙伴们团聚。小A等得很心急,所以他求助于你。请你告诉他,他和小伙伴们团聚所需要的时间。
对于100%的数据,3<=N, M<=50,1<=K<=5如果小A和他的小伙伴们能够团聚,团聚的总秒数小于10^18。
Solution
显然我们需要找循环节。
首先将每个点拆成四个状态,从不同方向进入。
先考虑在环内。
根据环中到达小A点的状态,可以列出方程组。
T=X+kY
X表示第一次在环中到这个状态的时间,Y表示环的长度。
那就是
T≡X(modY)
对于同一个人可能在环中从不同方向经过目标点,那么就枚举选哪一个。
现在要解最小的T
观察
T≡X1(modY1)
T≡X2(modY2)
合并后的式子就是
T≡A(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);
}
}