持续创作,加速成长!这是我参与「掘金日新计划 · 6 月更文挑战」的第8天,点击查看活动详情
奶牛芭蕾
为了挑战人们将奶牛视为笨拙生物的成见,农夫约翰的奶牛贝茜报名参加了芭蕾舞入门班。
她的最后一场演出是下周,约翰想帮她搭建一个足够大的长方形舞台,这样她就可以在不从舞台边沿跌落的情况下表演整个舞蹈。
贝茜的舞蹈将在一个长方形的舞台上进行,这个舞台可以看作由 1×11×1 的单元格组成的矩阵。
贝茜的四只脚被简明扼要地描述如下:
FR:右前脚
FL:左前脚
RR:右后脚
RL:左后脚
她的四只脚最开始位于四个相邻的单元格中,这四个单元格可以构成一个小正方形,如下所示,贝茜朝北站立:
FL FR
RL RR
贝茜的舞蹈遵循一系列 NN 条指令,每条指令要么指示她将一只脚移动一个单元格,要么指示她顺时针转动 9090 度。
移动脚的指令由 33 个字符组成,前两个字符表明要移动的脚,最后一个字符指定移动方向(FF = 前进,BB = 后退,RR = 右,LL = 左)。
例如,FRFFRF 表示贝茜应该将她的右前脚向前移动一个单元格,RLRRLR 表示她应该将她的左后脚向右移动一个单元格。
当然,运动的方向与贝茜面对的方向是相对的。
贝茜的顺时针转动是以某一只脚作为枢轴而进行的,转动时枢轴脚应保持竖立,并围绕该脚进行顺时针转动。
顺时针转动的指令也由 33 个字符组成,前两个字符表明枢轴脚,最后一个字符为 PP,表示该脚作为枢轴。
例如,FRPFRP 表示贝茜应该以右前脚作为枢轴,围绕其顺时针旋转 9090 度。
这意味着,如果贝茜的脚现在处于如下位置(贝茜朝北站立):
.. .. ..
.. .. FR
.. FL ..
.. RL RR
执行完 FRPFRP 指令以后,她的脚将位于如下位置,贝茜现在朝东站立:
RL FL ..
RR .. FR
.. .. ..
.. .. ..
给定贝茜舞蹈的 NN 条指令,请计算能够使贝茜全程不踩空跌落的长方形舞台的最小面积。
如果贝茜将一只脚移动到与另一只脚相同的单元格内,她就会被绊倒,从而无法完成舞蹈。
这种情况下,请输出 −1−1。
注意,这是贝茜唯一能够被绊倒的情况,在经过所有练习以后,贝茜十分灵活,很容易摆出各种高难度姿势(例如,后脚比前脚更向前)。
输入格式
第一行包含整数 NN。
接下来 NN 行,每行包含三个字符,表示一个舞蹈指令。
输出格式
输出在整个舞蹈过程中,能够容纳贝茜的脚所必须的长方形舞台的最小面积。
如果贝茜被绊倒,则输出 −1−1。
数据范围
1≤N≤10001≤N≤1000
输入样例:
3
FRF
FRP
RLB
输出样例:
16
样例解释
贝茜需要一个 4×44×4 大小的舞台,保证她能够完成她的舞蹈。
她的脚步如下:
.. .. .. ..
.. .. .. .. (朝北)
.. .. FL FR
.. .. RL RR
执行 FRFFRF 后:
.. .. .. ..
.. .. .. FR (朝北)
.. .. FL ..
.. .. RL RR
执行 FRPFRP 后:
.. RL FL ..
.. RR .. FR (朝东)
.. .. .. ..
.. .. .. ..
执行 RLBRLB 后:
RL .. FL ..
.. RR .. FR (朝东)
.. .. .. ..
.. .. .. ..
代码:
import java.util.*;
public class Main{
static int n,minx, maxx, miny, maxy;
static int x[] = {0, 1, 1, 0}; // 0FL, 1FR, 2RR, 3RL
static int y[] = {1, 1, 0, 0};
static int dx[] = {0, 1, 0, -1}; //0前(上), 1右, 2后(下), 3左
static int dy[] = {1, 0, -1, 0};
static int d; // 当前方向
//交换位置
public static void swap(int a){
int temp = x[a];
x[a] = y[a];
y[a] = temp;
}
public static void main(String[] args){
Scanner scan = new Scanner(System.in);
n = scan.nextInt(); // 输入n
for (int i = 1; i <= n; i++) { //输入n个样例
String s = scan.next(); //输入字符串
char a = s.charAt(0); //将字符串转化成字符类型
char b = s.charAt(1);
char op = s.charAt(2);
int f = 0; //f表示当前是哪个腿,对应的编号// 0FL, 1FR, 2RR, 3RL
if (a == 'F' && b == 'L') f = 0; // 前左腿
if (a == 'F' && b == 'R') f = 1; // 前右腿
if (a == 'R' && b == 'R') f = 2; // 后右腿
if (a == 'R' && b == 'L') f = 3; // 后左腿
if (op == 'F') { //前进
x[f] += dx[d];y[f] += dy[d];
}else if (op == 'B') { //后退
//d表示面对的方向,d+2表示向后的方向,可以看一下上面对应的每一个方向的坐标,
//所以只需要(d+2) % 4 就能够向后的方向走
x[f] += dx[(d + 2) % 4];y[f] += dy[(d + 2) % 4];
}else if (op == 'L') { //向左
//d+3,表示向左的方向,就像是顺时针旋转了270度
x[f] += dx[(d + 3) % 4]; y[f] += dy[(d + 3) % 4];
}else if (op == 'R') { //向右
//d+1,表示向右的方向,比如0是前进方向,向右就是1方向
x[f] += dx[(d + 1) % 4];y[f] += dy[(d + 1) % 4];
}else if (op == 'P') { //顺时针旋转90度
//旋转之后改变方向,因为每一次顺时针旋转之后都是方向会向右转,
//所以我们的方向会在0-3之间进行变换,所以每一次旋转只需要(当前方向 + 1) % 4
d = (d + 1) % 4;
//下面是枚举所有点,将每一个点旋转之后,点对应的坐标,详情看图
int x0 = x[f], y0 = y[f];
for (int j = 0; j <= 3; j++) {
if (j == f) continue;//因为如果是轴点,则旋转之后也不会变
int xx = x0 + y[j] - y0;
int yy = y0 + x0 - x[j];
x[j] = xx;
y[j] = yy;
}
}
//枚举有没有在同一个位置的两条腿
for (int k = 0; k <= 3; k++)
for (int u = k + 1; u <= 3; u++)
if (x[k] == x[u] && y[k] == y[u]) { // 绊倒
System.out.println("-1");
return;
}
//枚举四个腿,留下最大的跟最小的x轴方向的值,求其差值,就是最大矩形舞台的横坐标长度
//y轴也同理
for (int res = 0; res <= 3; res++) {
minx = Math.min(minx, x[res]);
miny = Math.min(miny, y[res]);
maxx = Math.max(maxx, x[res]);
maxy = Math.max(maxy, y[res]);
}
}
//求其差值,就是最大矩形舞台的横坐标长度 (横坐标差值 * 纵坐标差值)
System.out.println((maxx - minx + 1) * (maxy - miny + 1) );
}
}