1. 程式人生 > >洛谷P2206 奶牛芭蕾

洛谷P2206 奶牛芭蕾

題目描述

她的期末彙報演出就在下週,於是Farmer Jhon 就幫她建一個長方形的舞臺。

為了防止Bessie從舞臺邊緣掉下,FJ決定要建一個足夠大的舞臺。

Bessie的舞蹈將會佔用一個由許多1 x 1的正方形方塊組成的長方形的區域。為了方便,我們把Bessie的四隻腳按如下方式簡寫:

FR : 前右腳(Front right foot)

FL :前左腳(Front left foot)

RR :後右腳(Rear right foot)

RL :後左腳(Rear left foot)

Bessie將會從一個如下的四個相鄰的格子出發,同時她會面向北方。

FL FR

RL RR

Bessie的舞蹈會依據總數為N(1 <= N <= 1000 ) 的指令進行。每一條指令都指示Bessie將一隻腳移動一個格子,或者順時針旋轉90°

其中,移動的指示由三個字元組成,其中前兩個是腳的代號,最後一個代表腳移動的方向("F" - 向前 "B" - 向後 "R" - 向右 "L" - 向左)

比如說, "FRF"代表著Bessie的前右腳向前移動一個格子,"RLR"代表她的後左腳將向右移一個格子

當然,我們這裡說的方向是以Bessie正面對的方向決定的。

另一方面,旋轉的指令也是3個字元,其中前兩個字母也是腳的代號,代表著旋轉的支點。最後一個字母總是為"P"(pivot)。

比如說, "FRP"代表著Bessie將以前右腳為支點,順時針旋轉90°。

如果我們從圖中看,假設現在Bessie的腳是這樣的,她正朝向北方。

.. .. ..

.. .. FR

.. FL ..

.. RL RR

那麼在進行指令"FRP"之後,她的腳的位置將變成下面這樣,同時她將會朝向左邊:

RL FL ..

RR .. FR

.. .. ..

.. .. ..

現在已知N條Bessie的舞蹈的指令,請你計算她的整個舞蹈所需要的最小的長方形舞臺,使得Bessie的腳不會落到舞臺之外。

如果無論怎麼樣,她都會使自己的兩個腳移動到相同的格子裡,那麼她就會被絆倒,並搞砸這次表演。

在這樣的情況下,請輸出-1。

不過這是Bessie會被絆倒的唯一的原因,因為她在經過練習之後,身體十分的柔軟,可以輕鬆的做到任何奇怪的動作(比如說把後腳伸到前腳的前面)

(吐槽:那你就不能兩隻腳放在一起?)

(吐槽2:如果你覺得裡面的配圖有點怪異的話,就把它複製到記事本 ,把字型改成Courier New即可)

輸入輸出格式

輸入格式:

 

第一行是整數N ( 1 <= N <= 1000)

第二至N+1行是如題所述的指令,每行有三個字元

 

輸出格式:

 

一行,輸出舞臺的最小面積

 

輸入輸出樣例

輸入樣例#1:

3
FRF
FRP
RLB

輸出樣例#1:

16

 

這道題並不是很難,只是模擬起來很噁心,我們要學會化簡模擬,比如說利用轉化的思想

其實操作只有兩種,一種是某一個腳朝一個方向走一格,另一種是以一隻腳為中點順時針選擇90度

我們先想想bessie一開始站在平面直角座標系上,左後腳站在原點,朝著x的正半軸及上方

為了化簡我設定了

b[]分別表示Bessie的四個腳

b[0]表示前左腳
b[1]表示前右腳
b[2]表示後左腳
b[3]表示後右腳

 

pos表示bessie當前的方向

pos=0表示朝上
pos=1表示朝左
pos=2表示朝下
pos=3表示朝右

'F' 'B' 'L' 'R'分別表示操作0,1,2,3

'P‘表示操作4

以下是模擬兩種操作的方法

 

操作1:

 這個操作就利用了化簡的思想

如果需要走,我們只需要改變當前腳的座標

不是有搜尋矩陣的題目嗎,需要往上下左右四個方向搜尋

我們也可以利用這種方向的思想,來定義兩個陣列,一個存x座標的改變,另一個存y座標的改變

我用的常量是operax[][]和operay[][]

因此我們可以這樣利用兩個陣列

x+=operax[方向][操作]

y+=operay[方向][操作]

 

操作2:

很顯然,操作二是一個難點

我們就利用一個函式:

huan(k,centre)//表示將第k只腳以第cntre為中心旋轉90度

那怎麼轉呢?

首先把固定的那隻腳想象成原點,別的腳都有對應的關係

舉個例子,我們把固定的腳變成原點,並且假設要旋轉的腳是在(1,2)

給個圖片:


這個圖好像比較大,不過很清楚的看出,點是如何旋轉的

設要旋轉的點為(x,y),旋轉完後變成點(y,-x)

這就是旋轉的方法了

下面就是各位最想要的程式碼:

#include<cstdio>
#include<cstring>
#include<algorithm>
#include<iostream>
#include<cstdlib>
#include<queue>
#include<stack>
#include<cmath>
#include<map>
using namespace std;
struct zb{
    int x,y;
}B[4];//分別表示Bessie的四個腳
//b[0]表示前左腳
//b[1]表示前右腳
//b[2]表示後左腳
//b[3]表示後右腳
int pos;//表示方向
//pos=0表示朝上
//pos=1表示朝左
//pos=2表示朝下
//pos=3表示朝右
const int operax[4][4]={//opera[pos][order],表示腳往哪個方向走多少步 
    0,0,-1,1,
    -1,1,0,0,
    0,0,1,-1,
    1,-1,0,0};
const int operay[4][4]={
    1,-1,0,0,
    0,0,-1,1,
    -1,1,0,0,
    0,0,1,-1};
char ss[5];
inline int foot(){//根據字串判斷腳 
    if(ss[0]=='F'){
        if(ss[1]=='L')return 0;
        return 1;
    }
    else{
        if(ss[1]=='L')return 2;
        return 3;
    }
}
inline int order(){//判斷命令 
         if(ss[2]=='F')return 0;
    else if(ss[2]=='B')return 1;
    else if(ss[2]=='L')return 2;
    else if(ss[2]=='R')return 3;
    return 4;
}
zb n1,n2;
inline void update(){//記錄左下角和右上角 
    for(int i=0;i<4;i++)
        n1.x=min(n1.x,B[i].x),
        n1.y=min(n1.y,B[i].y),
        n2.x=max(n2.x,B[i].x),
        n2.y=max(n2.y,B[i].y);
}
inline bool check(int t1){//判斷是否有和t1在同位的腳 
    for(int i=0;i<4;i++)if(i!=t1)
        if(B[i].x==B[t1].x&&B[i].y==B[t1].y)
            return 0;
    return 1;
}
inline void huan(int k,int centre){//旋轉函式 
    int x=B[k].x-B[centre].x;
    int y=B[k].y-B[centre].y;
    /*   if(x>=0&&y>=0)swap(x,y),y=-y;
    else if(x>=0&&y<=0)swap(x,y),y=-y;
    else if(x<=0&&y<=0)swap(x,y),y=-y;
    else               swap(x,y),y=-y;*/
    swap(x,y),y=-y;
    B[k].x=B[centre].x+x;
    B[k].y=B[centre].y+y;
}
int main(){ 
    B[0]=(zb){0,1};//腳的位置 
    B[1]=(zb){1,1};
    B[2]=(zb){0,0};
    B[3]=(zb){1,0};
    pos=0;
    n1=(zb){ 999999999, 999999999};//初始化 
    n2=(zb){-999999999,-999999999};
    int n,t1,t2;cin>>n;
    bool bk=1;
    while(n--){
        cin>>ss;
        t1=foot();t2=order();
        if(t2!=4){//兩種不同的操作 
            B[t1].x+=operax[pos][t2];
            B[t1].y+=operay[pos][t2];
            if(!check(t1)){bk=0;break;}
        }
        else{
            for(int i=0;i<4;i++)if(i!=t1)
                huan(i,t1);
            pos--;if(pos==-1)pos=3;
        }
        update();
    }
    if(bk==0)printf("-1\n");
    else printf("%d\n",(n2.x-n1.x+1)*(n2.y-n1.y+1));//記得+1 
    return 0;
}