[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 }

 

posted @ 2017-12-19 11:41  skylee03  阅读(166)  评论(0编辑  收藏  举报