[ARC087D]FT Robot
题目大意:
一个机器人按照给定的一系列指令进行运动。
总共有两种指令:
T:向某个方向旋转90度。
F:向当前所朝的方向走一个单位长度。
一开始机器人站在原点,且朝向x的正半轴方向,问机器人是否可能会经过点(x,y)。
思路:
不难想到一个O(n^3)的DP。
考虑如何重新设计状态来优化到O(n^2).
显然,横向运动的过程和纵向运动的过程是独立的。
我们不妨分开考虑这两种情况。
我们可以对于给定的指令序列分组,使得每一组的指令都是若干个F加上一个T的形式(当然也可以没有F)。
显然,这时候对于每一组的指令,机器人的运动情况都是向当前方向前进若干步再转弯。
而如果我们对每一组指令进行编号,显然,机器人移动的方向与组的编号有关。
编号为奇数的在水平方向上移动,反之则在竖直方向上移动。
以水平方向为例,用f[i]表示是否可能走到横坐标为i的位置,d[j]表示第j组中F的个数,那么f[i]=f[i-d[j]]||f[i+d[j]]。
其中如果第一个指令就是F,就只能往右走而不能往左走,要特判一下。
最后就只需要分别判断一下x和y是否可以到达即可。
1 #include<cstdio> 2 #include<cctype> 3 #include<cstring> 4 inline int getint() { 5 register char ch; 6 register bool neg=false; 7 while(!isdigit(ch=getchar())) if(ch=='-') neg=true; 8 register int x=ch^'0'; 9 while(isdigit(ch=getchar())) x=(((x<<2)+x)<<1)+(ch^'0'); 10 return neg?-x:x; 11 } 12 const int N=10001,M=20001; 13 char s[N]; 14 int op[N]={1}; 15 bool f[2][M],tmp[M]; 16 int main() { 17 scanf("%s",s); 18 const int x=getint(),y=getint(); 19 op[1]=s[0]=='F'; 20 for(register int i=1;s[i];i++) { 21 if(s[i]=='T'&&s[i-1]=='T') op[++op[0]]=0; 22 if(s[i]=='F') { 23 if(s[i-1]=='T') op[0]++; 24 op[op[0]]++; 25 } 26 } 27 f[0][N]=f[1][N]=true; 28 for(register int i=1;i<=op[0];i++) { 29 memset(tmp,0,sizeof tmp); 30 for(register int j=0;j<M-op[i];j++) tmp[j+op[i]]|=f[i&1][j]; 31 if(i!=1) for(register int j=op[i];j<M;j++) tmp[j-op[i]]|=f[i&1][j]; 32 memcpy(f[i&1],tmp,sizeof tmp); 33 } 34 puts(f[0][N+y]&&f[1][N+x]?"Yes":"No"); 35 return 0; 36 }