空间人物行走的向量实现(pku1835解题报告)
2010-07-17 16:46
381 查看
可以先看这道题目中的描述http://acm.pku.edu.cn/JudgeOnline/problem?id=1835
首先讨论数据结构。
由于我们的问题是在三维坐标下的,于是我们首先建立三维坐标下的数据结构三维向量类,为方便其运算同时封装它需要的运算。
第一个运算符*是向量的叉积,叉积的运算如右图所示,叉积不符合交换律。
第二个运算符*是向量的延长,这里主要用于产生位移向量。
第三个运算符+=是加上另一个向量。
对于空间内一个人,
比如航天员
astronaut,
他要完成前后左右转,那么就需要一个变量表示他的面朝哪边后文称面向量,他要完成上下转我们还需要知道哪个方向对他来说是上,于是我们还需要一个向量表示他的头朝哪边后文称为头向量,同时我们还必须一个向量来表示他在空间中的位置后文称位置向量。现在我们总共需要三个向量:面向量,头向量,位置向量。用f(face)h(head)pos(position)表示。
然后我们讨论基于这个数据结构完成的上下左右前后转动的算法。
前进不需要转动,后退只需要把面向量乘以-1即可。
下面讨论左右上下转动。
![](http://upload.wikimedia.org/wikipedia/commons/thumb/d/df/Crossproduct.png/220px-Crossproduct.png)
如图,假设a向量为头向量,b向量为面向量,那么我们可以发现a*b就是他左转以后的面向量,b*a就是他右转以后的面向量,而左右转的时候头向量是不变的。
向上与向下也很简单,向上转动以后,头朝着之前面向量相反的方向。面朝着之前的头的方向。
向下转动,头朝着之前的面向量,面朝着之前头向量的相反方向。程序实现的时候要注意转之前与转之后变量的变化与使用。
转动完了以后就讨论行走了。
由于面向量使用单位向量,于是转动以后的行走多少单位就是面向量乘以多少,这个叫做位移向量,位置向量加上位移向量就完成了一次行走了。
这里注意产生位移向量的时候要保证面向量是单位向量,由于这道题的转动都是直角转动,且面向量与头向量垂直,所以叉乘以后的向量模|a||b|sin90还是1可以直接拿来用
。
下面是行走的算法,cmd表示指令,m表示距离。astronaut是people类的全局变量,在people类的定义后声明过了。
我这里为方便起见使用了右手螺旋坐标,而题目上是左手螺旋坐标,在输出时需要简单处理一下,只需改变一下y轴符号即可,下面是main函数。
首先讨论数据结构。
由于我们的问题是在三维坐标下的,于是我们首先建立三维坐标下的数据结构三维向量类,为方便其运算同时封装它需要的运算。
struct vector3 { int x, y, z; vector3 operator *(vector3 b) { vector3 ans; ans.x = y * b.z - z * b.y; ans.y = z * b.x - x * b.z; ans.z = x * b.y - y * b.x; return ans; } vector3 operator *(int k) { vector3 ans; ans.x = x*k; ans.y = y*k; ans.z = z*k; return ans; } vector3 operator +=(vector3 b) { x += b.x; y += b.y; z += b.z; return *this; } };
第一个运算符*是向量的叉积,叉积的运算如右图所示,叉积不符合交换律。
第二个运算符*是向量的延长,这里主要用于产生位移向量。
第三个运算符+=是加上另一个向量。
对于空间内一个人,
比如航天员
astronaut,
他要完成前后左右转,那么就需要一个变量表示他的面朝哪边后文称面向量,他要完成上下转我们还需要知道哪个方向对他来说是上,于是我们还需要一个向量表示他的头朝哪边后文称为头向量,同时我们还必须一个向量来表示他在空间中的位置后文称位置向量。现在我们总共需要三个向量:面向量,头向量,位置向量。用f(face)h(head)pos(position)表示。
struct people { vector3 f, h, pos; } astronaut;
然后我们讨论基于这个数据结构完成的上下左右前后转动的算法。
前进不需要转动,后退只需要把面向量乘以-1即可。
下面讨论左右上下转动。
![](http://upload.wikimedia.org/wikipedia/commons/thumb/d/df/Crossproduct.png/220px-Crossproduct.png)
如图,假设a向量为头向量,b向量为面向量,那么我们可以发现a*b就是他左转以后的面向量,b*a就是他右转以后的面向量,而左右转的时候头向量是不变的。
向上与向下也很简单,向上转动以后,头朝着之前面向量相反的方向。面朝着之前的头的方向。
向下转动,头朝着之前的面向量,面朝着之前头向量的相反方向。程序实现的时候要注意转之前与转之后变量的变化与使用。
转动完了以后就讨论行走了。
由于面向量使用单位向量,于是转动以后的行走多少单位就是面向量乘以多少,这个叫做位移向量,位置向量加上位移向量就完成了一次行走了。
这里注意产生位移向量的时候要保证面向量是单位向量,由于这道题的转动都是直角转动,且面向量与头向量垂直,所以叉乘以后的向量模|a||b|sin90还是1可以直接拿来用
。
下面是行走的算法,cmd表示指令,m表示距离。astronaut是people类的全局变量,在people类的定义后声明过了。
void walk(char* cmd, int m) { if (strcmp(cmd,"left")==0){ astronaut.f = astronaut.h * astronaut.f; astronaut.pos += astronaut.f*m; } if (strcmp(cmd,"right")==0) { astronaut.f = astronaut.f * astronaut.h; astronaut.pos += astronaut.f*m; } if (strcmp(cmd,"forward")==0) astronaut.pos += astronaut.f * m; if (strcmp(cmd,"back")==0) { astronaut.f = astronaut.f*-1; astronaut.pos += astronaut.f*m; } if (strcmp(cmd,"up")==0) { vector3 oldh = astronaut.h; astronaut.h=astronaut.f*-1; astronaut.f=oldh; astronaut.pos += astronaut.f*m; } if (strcmp(cmd,"down")==0) { vector3 oldh = astronaut.h; astronaut.h=astronaut.f; astronaut.f=oldh*-1; astronaut.pos += astronaut.f*m; } }
我这里为方便起见使用了右手螺旋坐标,而题目上是左手螺旋坐标,在输出时需要简单处理一下,只需改变一下y轴符号即可,下面是main函数。
int main(int argc, char** argv) { char cmd[10]; int t, n, m, i, face; scanf("%d",&t); while (t--) { astronaut.h.x = astronaut.h.y = astronaut.f.z = astronaut.f.y = astronaut.pos.x = astronaut.pos.y = astronaut.pos.z = 0; astronaut.h.z = astronaut.f.x = 1; scanf("%d",&n); while (n--) { scanf("%s%d",cmd,&m); walk(cmd, m); } if (astronaut.f.x > 0)face = 0; if (astronaut.f.x < 0)face = 3; if (astronaut.f.y < 0)face = 1; if (astronaut.f.y > 0)face = 4; if (astronaut.f.z > 0)face = 2; if (astronaut.f.z < 0)face = 5; printf("%d %d %d %d/n",astronaut.pos.x,-astronaut.pos.y,astronaut.pos.z,face); } return (EXIT_SUCCESS); }
相关文章推荐
- pku 1835解题报告
- PKU POJ 1611解题报告(并查集)
- PKU1061 解题报告 青蛙的约会 __用扩展欧几里得解模同余方程
- Pku acm 1007 DNA Sorting 排序算法解题报告(五)----求逆序数 排序
- pku 2421 Prim算法 Constructing Roads解题报告
- PKU 1679 The Unique MST(解题报告)
- pku 1961 KMP period 解题报告
- Pku acm 2159 Ancient Cipher 排序算法解题报告(六)----计数排序
- Pku acm 1274 The Perfect Stall 数据结构题目解题报告(十三)---- 匈牙利算法求二分图的最大匹配
- pku 1953 dp World Cup Noise 解题报告
- pku_1862 Stripies 解题报告
- Pku acm 2492 A Bug's Life数据结构题目解题报告(十)---- 并查集的应用
- pku_1256 Anagram 解题报告
- pku 1664 放苹果 整数拆分 解题报告
- pku 2389解题报告
- pku 树形dp 1849 two 解题报告
- pku1160 Post Office 解题报告
- pku 1947 Rebuilding Roads 树形dp 解题报告
- pku 1129 channel allocation 回溯解题报告
- POJ 1006Biorhythms解题报告——生理周期——【PKU ACM】