BZOJ2647 : [Neerc2011]Journey
$|x|+|y|=\max(x+y,x-y,-x+y,-x-y)$,设$f[i][j]$表示在$(0,0)$,朝向方向$j$,执行第$i$条指令后的信息:
$cir$:是否陷入循环
$d$:朝向
$x,y$:坐标
$v_0$:$\max(x+y)$
$v_1$:$\max(x-y)$
$v_2$:$\max(-x+y)$
$v_3$:$\max(-x-y)$
然后记忆化搜索,当陷入循环时不再执行后面的指令。
用栈维护所有正在计算的状态,若发现循环,则计算循环的$x$和$y$之和,若为$0$则是循环,否则会走到无限远处。
时间复杂度$O(n^3)$。
#include<cstdio> #include<string> #include<iostream> #include<cstdlib> using namespace std; const int N=110,Base=100000000,MAXL=32; int n,i,j,a[N],q[N*4][2],in[N][4];string b[N][N];bool vis[N][4],cir[N][4]; inline int max(int a,int b){return a>b?a:b;} struct Num{ int a[MAXL],len,fu; void init(){len=1,fu=a[1]=0;} Num(){init();} bool iszero(){return len==1&&!a[1];} Num operator+(const Num&b){ Num c; c.len=max(len,b.len)+2; int i; for(i=1;i<=c.len;i++)c.a[i]=0; if(fu==b.fu){ for(i=1;i<=len;i++)c.a[i]=a[i]; for(i=1;i<=b.len;i++)c.a[i]+=b.a[i]; for(i=1;i<=c.len;i++)if(c.a[i]>=Base)c.a[i+1]++,c.a[i]-=Base; while(c.len>1&&!c.a[c.len])c.len--; c.fu=fu; }else{ bool flag=0; if(len==b.len){ for(i=len;i;i--)if(a[i]!=b.a[i]){ if(a[i]>b.a[i])flag=1; break; } }else{ if(len>b.len)flag=1; } if(flag){ for(i=1;i<=len;i++)c.a[i]=a[i]; for(i=1;i<=b.len;i++)c.a[i]-=b.a[i]; for(i=1;i<=c.len;i++)if(c.a[i]<0)c.a[i+1]--,c.a[i]+=Base; while(c.len>1&&!c.a[c.len])c.len--; c.fu=fu; }else{ for(i=1;i<=b.len;i++)c.a[i]=b.a[i]; for(i=1;i<=len;i++)c.a[i]-=a[i]; for(i=1;i<=c.len;i++)if(c.a[i]<0)c.a[i+1]--,c.a[i]+=Base; while(c.len>1&&!c.a[c.len])c.len--; c.fu=b.fu; } } if(c.iszero())c.init(); return c; } void operator+=(const Num&b){*this=*this+b;} Num operator-(const Num&b){ Num c; c.len=max(len,b.len)+2; int i; for(i=1;i<=c.len;i++)c.a[i]=0; if(fu!=b.fu){ for(i=1;i<=len;i++)c.a[i]=a[i]; for(i=1;i<=b.len;i++)c.a[i]+=b.a[i]; for(i=1;i<=c.len;i++)if(c.a[i]>=Base)c.a[i+1]++,c.a[i]-=Base; while(c.len>1&&!c.a[c.len])c.len--; c.fu=fu; }else{ bool flag=0; if(len==b.len){ for(i=len;i;i--)if(a[i]!=b.a[i]){ if(a[i]>b.a[i])flag=1; break; } }else{ if(len>b.len)flag=1; } if(flag){ for(i=1;i<=len;i++)c.a[i]=a[i]; for(i=1;i<=b.len;i++)c.a[i]-=b.a[i]; for(i=1;i<=c.len;i++)if(c.a[i]<0)c.a[i+1]--,c.a[i]+=Base; while(c.len>1&&!c.a[c.len])c.len--; c.fu=fu; }else{ for(i=1;i<=b.len;i++)c.a[i]=b.a[i]; for(i=1;i<=len;i++)c.a[i]-=a[i]; for(i=1;i<=c.len;i++)if(c.a[i]<0)c.a[i+1]--,c.a[i]+=Base; while(c.len>1&&!c.a[c.len])c.len--; c.fu=b.fu^1; } } if(c.iszero())c.init(); return c; } void operator-=(const Num&b){*this=*this-b;} bool operator<(const Num&b){ if(fu!=b.fu)return fu; if(fu){ if(len!=b.len)return len>b.len; for(int i=len;i;i--)if(a[i]!=b.a[i])return a[i]>b.a[i]; }else{ if(len!=b.len)return len<b.len; for(int i=len;i;i--)if(a[i]!=b.a[i])return a[i]<b.a[i]; } return 0; } void write(){ if(fu)putchar('-'); printf("%d",a[len]); for(int i=len-1;i;i--)printf("%08d",a[i]); } void set(int x){ fu=0; if(x<0)x=-x,fu=1; len=1; a[1]=x; } }zero,one,x,y; inline void up(Num&a,const Num&b){if(a<b)a=b;} struct E{ int d;Num x,y,v0,v1,v2,v3; void left(){d=(d+1)&3;} void right(){d=(d+3)&3;} void init(int _d){ d=_d; x.set(0); y.set(0); v0.set(0); v1.set(0); v2.set(0); v3.set(0); } void go(){ if(d==0)x+=one; if(d==1)y+=one; if(d==2)x-=one; if(d==3)y-=one; up(v0,x+y); up(v1,x-y); up(v2,y-x); up(v3,zero-x-y); } void merge(const E&b){ d=b.d; up(v0,x+y+b.v0); up(v1,x-y+b.v1); up(v2,y-x+b.v2); up(v3,zero-x-y+b.v3); x+=b.x; y+=b.y; } void write(){ up(v0,v1); up(v0,v2); up(v0,v3); v0.write(); } }f[N][4]; inline int cal(const string&s){ int t=0; for(int i=1;i<s.size();i++)t=t*10+s[i]-'0'; return t; } inline void check(int l,int r){ for(x.set(0),y.set(0);l<=r;l++)x+=f[q[l][0]][q[l][1]].x,y+=f[q[l][0]][q[l][1]].y; if(x.iszero()&&y.iszero())return; puts("Infinity"); exit(0); } void cal(int x,int y,int d){ if(vis[x][y])return; vis[x][y]=1; q[in[x][y]=d][0]=x; q[d][1]=y; f[x][y].init(y); for(int i=0;i<a[x];i++){ if(b[x][i]=="GO")f[x][y].go(); else if(b[x][i]=="LEFT")f[x][y].left(); else if(b[x][i]=="RIGHT")f[x][y].right(); else{ int A=cal(b[x][i]),B=f[x][y].d; if(in[A][B]){ check(in[A][B],d); cir[x][y]=1; }else{ cal(A,B,d+1); f[x][y].merge(f[A][B]); if(cir[A][B])cir[x][y]=1; } if(cir[x][y])break; } } in[x][y]=0; } int main(){ zero.set(0); one.set(1); cin>>n; for(i=1;i<=n;i++){ cin>>a[i]; for(j=0;j<a[i];j++)cin>>b[i][j]; } cal(1,0,1); f[1][0].write(); return 0; }