给四条线段,判断是否是矩形
2015-06-11 20:25
399 查看
今天又做了一个题目,这个感觉比昨天的复杂一些,代码量都多了一些。
题目是这样的,要求输入一系列点坐标,一共输入16个整型,两个两个一对,就是8个坐标,再两个两个一对,就是4条线段,判断这4条线段,是否围成一个矩形。
想了下,大概分为如下几个步骤来做:
1. 获取输入,组织数据结构,怎么存储这些点,这些线段。
2. 然后就是怎么判断矩形。
怎么判断矩形?我又分为下面几个步骤来考虑:
1. 先判断四条线段是否首尾相连在一起。可以判定图形是否是封闭图形。
2. 四条线段中对于任意一条线段与其非相邻线段是否平行。做两次平行判断,可以判定为平行四边形。
3. 在平行四边形的基础上,判断任意两条相邻的线段是否垂直。有垂直就是直角了,也就是矩形。
4. 判断每一条线段的长度都不为0。
首先我是自定了一些数据结构来存储输入的数据,Point, Line, Rectangle, RectangleSet。
然后通过输入获取了点的信息后,需要做一个首尾相连的判断。我的基本思路是,首先将第一条线段作为起始线段,任意选一个端点作为last端点。然后遍历剩下的线段,判断每一条线段中的两个端点是否与last端点相同,如果相同,就把这条线段的另一个端点赋值给last端点,这样两条线段就连接上了,最后循环结束后,判断下第一条线段的另一个端点与最后不断赋值得到的last端点是否是同一个点,就完事了。
在这个遍历的过程中,我添加了一个order的属性,第一条起始线段order为1,其他的order为-1,当发现一条与第一条相连的线段是,将其order值改为2,依序进行,就按顺序将首尾相连的线段标记为1,2,3,4的order值了。
有了order值后,如果图形是个首尾相连的封闭图形,那么就判断平行了,有了order值就很方便,只需要判断1与3是否平行,2与4是否平行即可。
平行如果也达成了,那么就随便判断1与2是否是垂直关系就好了。
最后再判断下每条线段是否为0长度,这样就可以判断是否是矩形了。
因为是用C++写的,各种坑啊……VS调试起来也不熟练。
代码如下:
心得体会:感觉C++真的需要不断的练习才能熟练,这是我写的第二个比较复杂的C++程序了……这个解题的程序在hiro上并没有跑成功,它说我答案不对,题目给的三个测试用例,我都通过了,但又不知道如果搞到更多的测试用例……
题目是这样的,要求输入一系列点坐标,一共输入16个整型,两个两个一对,就是8个坐标,再两个两个一对,就是4条线段,判断这4条线段,是否围成一个矩形。
想了下,大概分为如下几个步骤来做:
1. 获取输入,组织数据结构,怎么存储这些点,这些线段。
2. 然后就是怎么判断矩形。
怎么判断矩形?我又分为下面几个步骤来考虑:
1. 先判断四条线段是否首尾相连在一起。可以判定图形是否是封闭图形。
2. 四条线段中对于任意一条线段与其非相邻线段是否平行。做两次平行判断,可以判定为平行四边形。
3. 在平行四边形的基础上,判断任意两条相邻的线段是否垂直。有垂直就是直角了,也就是矩形。
4. 判断每一条线段的长度都不为0。
首先我是自定了一些数据结构来存储输入的数据,Point, Line, Rectangle, RectangleSet。
然后通过输入获取了点的信息后,需要做一个首尾相连的判断。我的基本思路是,首先将第一条线段作为起始线段,任意选一个端点作为last端点。然后遍历剩下的线段,判断每一条线段中的两个端点是否与last端点相同,如果相同,就把这条线段的另一个端点赋值给last端点,这样两条线段就连接上了,最后循环结束后,判断下第一条线段的另一个端点与最后不断赋值得到的last端点是否是同一个点,就完事了。
在这个遍历的过程中,我添加了一个order的属性,第一条起始线段order为1,其他的order为-1,当发现一条与第一条相连的线段是,将其order值改为2,依序进行,就按顺序将首尾相连的线段标记为1,2,3,4的order值了。
有了order值后,如果图形是个首尾相连的封闭图形,那么就判断平行了,有了order值就很方便,只需要判断1与3是否平行,2与4是否平行即可。
平行如果也达成了,那么就随便判断1与2是否是垂直关系就好了。
最后再判断下每条线段是否为0长度,这样就可以判断是否是矩形了。
因为是用C++写的,各种坑啊……VS调试起来也不熟练。
代码如下:
/* 输入四个点,判断是否是矩形 */ #include<iostream> using namespace std; class Point { public: int x, y = -1; //默认值负一 Point() {} ~Point() {} bool equals (Point p) { if (p.x == x && p.y == y) { return true; } else { return false; } } }; class Line { public: Point* start; Point* end; int order; //排序值 Line() { start = NULL; end = NULL; order = -1; } ~Line() {} bool isParallel(Line* line) { int deltaX1 = end->x - start->x; int deltaY1 = end->y - start->y; int deltaX2 = line->end->x - line->start->x; int deltaY2 = line->end->y - line->start->y; if (deltaX1 == 0 || deltaX2 == 0) { if (deltaX1 == deltaX2) { return true; } else { return false; } } else { if (1.0 * deltaY1 / deltaX1 == 1.0* deltaY2 / deltaX1) { return true; } else { return false; } } } bool isVertical(Line* line) { int deltaX1 = end->x - start->x; int deltaY1 = end->y - start->y; int deltaX2 = line->end->x - line->start->x; int deltaY2 = line->end->y - line->start->y; if ((deltaX1 == 0 && deltaY2 == 0) || (deltaX2 == 0 && deltaY1 == 0)) { //cout << "分母是0" << endl; return true; } double result = 1.0 * deltaY1 / deltaX1 * deltaY2 / deltaX2; //cout << "result:" <<result<< endl; if (result == 1 || result == -1) { return true; } else { return false; } } bool isZeroLenght() { if (start->equals(*end)) { return true; } else { return false; } } }; class Rectangle { public: Line* lineSet = NULL; Rectangle(){ lineSet = new Line[4]; } ~Rectangle(){ //delete lineSet; } void addLine(int index, Line line) { if (lineSet == NULL) { lineSet = new Line[4]; } lineSet[index] = line; } bool isRectangle() { //先判断是否首尾相连 Line firstLine = lineSet[0]; int currentOrder = lineSet[0].order = 1; Point lastPoint = *firstLine.start; Point firstPoint = *firstLine.end; for (int time = 1; time <= 3; time++) { //需要判断三次吧 bool isFound = false; for (int i = 0; i < 4 && !isFound; i++) { //从第一条开始 if (lineSet[i].order == -1) { //未排序的才可以进行判断 if (lineSet[i].start->equals(lastPoint)) { lineSet[i].order = ++currentOrder; //前自增,先自增再赋值 //cout << "order:" << currentOrder << endl; lastPoint = *lineSet[i].end; isFound = true; } else if (lineSet[i].end->equals(lastPoint)) { lineSet[i].order = ++currentOrder; //cout << "order:" << currentOrder << endl; lastPoint = *lineSet[i].start; isFound = true; } if (i == 3 && isFound == false) { return false; } } /* Line b1 = lineSet[0]; Line b2 = lineSet[1]; Line b3 = lineSet[2]; Line b4 = lineSet[3]; */ } } if (!lastPoint.equals(firstPoint)) { return false; } //首尾相连通过 /* Line a1 = lineSet[0]; Line a2 = lineSet[1]; Line a3 = lineSet[2]; Line a4 = lineSet[3]; Line* l1 = getLineByOrder(1); Line* l2 = getLineByOrder(2); Line* l3 = getLineByOrder(3); Line* l4 = getLineByOrder(4); */ //第二步,判断是否平行 if (!getLineByOrder(1)->isParallel(getLineByOrder(3)) || !getLineByOrder(2)->isParallel(getLineByOrder(4))) { //cout << "不平行" << endl; return false; } //第三步,判断一个垂直即可 bool hasVertical = false; for (int i = 0; i < 4 && !hasVertical; i++) { if (getLineByOrder((i + 1) % 4)->isVertical(getLineByOrder((i + 2) % 4))) { hasVertical = true; } if (i = 3 && !hasVertical) { //cout << "不垂直" << endl; return false; } } //第四步,判断有没有某条线是0长度 for (int i = 0; i < 4; i++) { if (lineSet[i].isZeroLenght()) { //cout << "0长度" << endl; return false; } } return true; } Line* getLineByOrder(int order) { for (int i = 0; i < 4; i++) { if (lineSet[i].order == order) { return &lineSet[i]; } } return NULL; } }; class RectangleSet { public: Rectangle* rectangleSet = NULL; RectangleSet(){} RectangleSet(int count) { rectangleSet = new Rectangle[count]; } ~RectangleSet(){} }; void run1040() { int m = 0; cin >> m; int x1, x2, y1, y2 = -1; RectangleSet* set = new RectangleSet(m); for (int i = 0; i < m; i++) { Rectangle* rec = new Rectangle(); for (int j = 1; j <= 4; j++) { //一轮输入中需要输4次 Point* p1 = new Point(); Point* p2 = new Point(); Line* line = new Line(); //cout << "请输入四个整型"<<endl; cin >> x1 >> y1 >> x2 >> y2; /* cout << x1 << endl; cout << x2 << endl; cout << y1 << endl; cout << y2 << endl; */ p1->x = x1; p1->y = y1; p2->x = x2; p2->y = y2; line->start = p1; line->end = p2; rec->addLine(j - 1, *line); } set->rectangleSet[i] = *rec; } for (int i = 0; i < m; i++) { Rectangle rec = set->rectangleSet[i]; if (rec.isRectangle()) { cout << "YES" << endl; } else { cout << "NO" << endl; } } }
心得体会:感觉C++真的需要不断的练习才能熟练,这是我写的第二个比较复杂的C++程序了……这个解题的程序在hiro上并没有跑成功,它说我答案不对,题目给的三个测试用例,我都通过了,但又不知道如果搞到更多的测试用例……
相关文章推荐
- 使用C++实现JNI接口需要注意的事项
- 关于指针的一些事情
- c++ primer 第五版 笔记前言
- share_ptr的几个注意点
- Lua教程(一):在C++中嵌入Lua脚本
- Lua教程(二):C++和Lua相互传递数据示例
- C++联合体转换成C#结构的实现方法
- C++编写简单的打靶游戏
- C++变位词问题分析
- C/C++数据对齐详细解析
- C++基于栈实现铁轨问题
- C++中引用的使用总结
- C++中调用Lua函数实例
- Lua和C++的通信流程代码实例
- C与C++之间相互调用实例方法讲解
- C++中拷贝构造函数的应用详解
- C++中引用(&)的用法与应用实例分析
- C++使用CriticalSection实现线程同步实例
- C++智能指针实例详解
- 解析C++ 浮点数的格式化输出