奶牛芭蕾

130 阅读5分钟

持续创作,加速成长!这是我参与「掘金日新计划 · 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) );
    }
}