POJ 1835 宇航员 解题报告

题意&样例:

宇航员在太空中迷失了方向,在他的起始位置现在建立一个虚拟xyz坐标系,称为绝对坐标系,宇航员正面的方向为x轴正方向,头顶方向为z轴正方向,则宇航员的初始状态如下图所示:

POJ 1835 宇航员 解题报告

现对六个方向分别标号,x,y,z正方向分别为0,1,2,负方向分别为3,4,5,称它们为绝对方向。宇航员在宇宙中只沿着与绝对坐标系xyz轴平行的方向行走,但是他不知道自己当前绝对坐标和自己面向的绝对方向。
请根据宇航员对自己在相对方向上移动的描述确定宇航员最终的绝对坐标和面向的绝对方向。对在相对方向上移动的描述及意义如下:

forward x  向前走x米。
back x 先转向后,再走x米。
left x 先转向左,再走x米。
right x 先转向右,再走x米。
up x 先面向上,再走x米。。
down x 先面向下,再走x米。

其中向上和向下如下图所示:
POJ 1835 宇航员 解题报告

输入

第一行是一个正整数m,表示测试数据的组数。每组测试数据第一行是一个正整数n(1≤n≤10000)表示宇航员行走的次数,下面n行每行输入一次相对行走,格式如上所述,其中1≤x≤10000。

输出

对于每组输入数据输出一行,x y z p,中间用空格隔开,x y z是宇航员的位置的绝对坐标,p是宇航员面向的绝对方向编号(0≤p≤5)。

样例输入

1
6
left 10
right 11
up 12
down 13
forward 14
back 15

样例输出

23 -10 12 3

样例结果

POJ 1835 宇航员 解题报告
思路:
该题核心是,这个人放在一个三维的空间里,他除了朝面部朝向的方向直走之外,向左向右向后亦或是向上向下改变方向行走,都会影响他的面朝向,左手朝向,以及头顶朝向这三个属性,而这三个属性决定了这个人下一次旋转再行走的绝对坐标,这样就必须,一直维护他的这三个属性,才能保证他每次换方向行走的绝对坐标无误,详解如下:
<1>首先初始化他的三个方向a, b, c。 a为面部朝向;b为左手朝向(左手系);c为头顶朝向,即初始化a = 0, b = 4, c = 2。
<2>然后研究他每次转动后他的三个属性朝向与转动前的联系:
i)向后转(back):头顶朝向不变,面朝向变为原面部朝向的逆,即原背部朝向,左手朝向变为原左手朝向的逆,即原右手朝向。
ps:处理手法,该题定义x, y, z轴的正方向为0, 1, 2,负方向为 3,4, 5,观察发现正负方向差值为3,所以可以用(p+3)% 6来改换为逆向,其中p为原来的方向。
ii) 向左转(left):头顶朝向不变,面部朝向变为原左手朝向,左手朝向变为原面部朝向的逆向,即原背部朝向。
iii) 向右转(right):头顶朝向不变,左手朝向变为原面部朝向,面部朝向变为原左手朝向的逆,即原右手朝向。
iv) 向上转(up):左手朝向不变,头顶朝向变为原面部朝向的逆,面部朝向变为原头顶朝向。
v) 向下转(down):左手朝向不变,头顶朝向变为原面部朝向,面部朝向变为原头顶朝向的逆。

代码如下:
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <cmath>
#include <algorithm>
#include <set>
#include <map>
#include <vector>
#include <ctime>
using namespace std;
typedef long long LL;
const int Maxx = 1e5 + 7;
const int Inf = 1e9;
const double PI     = acos(-1.0);
char s[13]; //朝向
int d; //步数
int dis; //每步的位移
int cas;
int x, y, z;
int a, b, c; //记录方向
int tmp;

int main() {
    scanf("%d", &cas);
    while(cas--) {
        scanf("%d", &d);
        x = 0, y = 0, z = 0;
        a = 0, b = 4, c = 2; //a为面朝向,b为左手朝向,c为竖直头顶朝向,左手坐标系故令b = 4
        while(d--) {
            scanf("%s %d", s, &dis);
            if(s[0] == 'b') a = (a + 3) % 6, b = (b + 3) % 6;
            else if(s[0] == 'l') tmp = a, a = b, b = (tmp + 3) % 6;
            else if(s[0] == 'r') tmp = b, b = a, a = (tmp + 3) % 6;
            else if(s[0] == 'u') tmp = a, a = c, c = (tmp + 3) % 6;
            else if(s[0] == 'd') tmp = c, c = a, a = (tmp + 3) % 6;
            if(a == 0) x += dis;
            else if(a == 1) y += dis;
            else if(a == 2) z += dis;
            else if(a == 3) x -= dis;
            else if(a == 4) y -= dis;
            else if(a == 5) z -= dis;
        }
        printf("%d %d %d %d\n", x, y, z, a);
    }
}