您的位置:首页 > 编程语言 > Java开发

hihocoder #1040 : 矩形判断 #java

2015-09-01 15:43 411 查看
时间限制:1000ms
单点时限:1000ms
内存限制:256MB


描述

给出平面上4条线段,判断这4条线段是否恰好围成一个面积大于0的矩形。


输入

输入第一行是一个整数T(1<=T<=100),代表测试数据的数量。
每组数据包含4行,每行包含4个整数x1, y1, x2, y2 (0 <= x1, y1, x2, y2 <= 100000);其中(x1, y1), (x2,y2)代表一条线段的两个端点。


输出

每组数据输出一行YES或者NO,表示输入的4条线段是否恰好围成矩形。

样例输入
3
0 0 0 1
1 0 1 1
0 1 1 1
1 0 0 0
0 1 2 3
1 0 3 2
3 2 2 3
1 0 0 1
0 1 1 0
1 0 2 0
2 0 1 1
1 1 0 1


样例输出
YES
YES
NO


解题思路


1:首先矩形必须是4个点。依次读取4条线段的2个点,进入map,key设为"x,y",重复的点会覆盖点。所以最后剩下4个点才继续向下判断,否则输出NO;


2:接下来判断四条线段之间是否平行或垂直。只需要拿边L1依次和其他三条边L2,L3,L4判断就可以了。


但是这时候有很多特殊情况,有4个点,4条边也平行或垂直,但也不一定构成矩形,如下图所示。我给的方法是,如果平行了,则不能有重合的点,平行边数量parallelNum加一;如果垂直了,则只有一个重合点,重合边数量verticalNum加一。


突然想起我忘记考虑【给出的一条边的两个点相同】,这个判断也简单,自己处理吧




代码:


import java.util.ArrayList;
import java.util.HashMap;
import java.util.Scanner;
public class Main {
ArrayList<Line> linesArray; //
public int[] result;  // 判断结果

public void entry(){
Scanner sc = new Scanner(System.in);
int number = sc.nextInt();
int[][][] lines = new int[number][4][4];  // 线段坐标
result = new int[number];
// input
for( int i=0; i<number; i++ ){
for( int j=0; j<4; j++ ){
for( int k=0; k<4; k++ ){
lines[i][j][k] = sc.nextInt();
}
}
}
// judge
for( int i=0; i<number; i++ ){
// 判读是否是4个点
if( pointsJudge(i, 4, lines[i]) == false ){
continue;
}
// 判断线段平行或垂直
linesJudge(i, linesArray);
}
// output
for(  int i=0; i<number; i++ ){
if( result[i] == 1 ){
System.out.println("YES");
}
else{
System.out.println("NO");
}
}
}

//  判断是否是 4 Points
public boolean pointsJudge(int rectangleNumber, int lineNumber, int[][] lines){
linesArray = new ArrayList<Line>();  // 线段数组
HashMap<String, Point> pointsMap = new HashMap<String, Point>();  // 点Map
for( int i=0; i<lineNumber; i++ ){
Line line = new Line(lines[i]);
linesArray.add(line);
Point point1 = line.getPoint1();  // p1
String key1 = point1.getKey();
pointsMap.put(key1, point1);
Point point2 = line.getPoint2();  // p2
String key2 = point2.getKey();
pointsMap.put(key2, point2);
}
if( pointsMap.size() != 4 ){  // 不是4个点
result[rectangleNumber] = 0;
return false;
}
return true;
}
// 线段平行,垂直判断
public int linesJudge(int rectangleNumber, ArrayList<Line> linesArray){
int x1 = linesArray.get(0).x1;
int y1 = linesArray.get(0).y1;
int x2 = linesArray.get(0).x2;
int y2 = linesArray.get(0).y2;
int verticalNum = 0;  // 垂直的线段数量
int parallelNum = 0;  // 平行的线段数量

for( int i=1; i<linesArray.size(); i++ ){
int x3 = linesArray.get(i).x1;
int y3 = linesArray.get(i).y1;
int x4 = linesArray.get(i).x2;
int y4 = linesArray.get(i).y2;
// 判断垂直
if( (y1-y2)*(y3-y4) == -1*(x1-x2)*(x3-x4) ){
// 垂直了,还得有一个点重复
if( (x1==x3)&&(y1==y3) || (x1==x4)&&(y1==y4) || (x2==x3)&&(y2==y3) || (x2==x4)&&(y2==y4) ){
verticalNum++;
continue;
}else{
result[rectangleNumber] = 0;
return 0;
}
}
// 判断平行
if( (y1-y2)*(x3-x4) == (y3-y4)*(x1-x2) ){
// 平行了,还得不能有点重复
if( (x1==x3)&&(y1==y3) || (x1==x4)&&(y1==y4) || (x2==x3)&&(y2==y3) || (x2==x4)&&(y2==y4) ){
result[rectangleNumber] = 0;
return 0;
}else{
parallelNum++;
continue;
}
}
// 既不平行也不垂直
result[rectangleNumber] = 0;
}
if( verticalNum==2 && parallelNum==1 ){  // 两垂直一平行
result[rectangleNumber] = 1;
}
return 1;
}

public static void main(String[] args){
Main m = new Main();
m.entry();
}

//
class Line{
int x1, y1, x2, y2;
Line(int[] line){
this.x1 = line[0];
this.y1 = line[1];
this.x2 = line[2];
this.y2 = line[3];
}
Point getPoint1(){
return new Point(this.x1, this.y1);
}
Point getPoint2(){
return new Point(this.x2, this.y2);
}
String getKey(){
return this.x1+","+this.y1+","+this.x2+","+this.y2;
}
}
//
class Point{
int x, y;
Point(int x, int y){
this.x = x;
this.y = y;
}
int getX(){
return this.x;
}
int getY(){
return this.y;
}
String getKey(){
return this.x+","+this.y;
}
}
}


[/code]
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: