这是移动研究院的一道笔试题,时间2018.10.21
这道题的核心点在于:如何判断一个直线和一个四边形相交
怎么判断:将每个顶点带入直线,如何全部大于0或者全部小于0,则直线不穿四边形,否则穿过四边形,这里面有一个特殊处理,如果有超过两个点的和恒等于0,则也可以认为直线穿过“四边形”
描述:
/*
* 题目描述
小B所在的公司正在开发一个网络游戏项目,他们需要解决场景中攻击双方的占位问题。根据场景设计,攻击双方可能位于某个四边形区域中。所有的攻击方沿直线方向,若攻击目标所在区域与攻击线有交点才能被击中。直线可以表达为Ax+by+C=0。小B希望确定按指定参数发出的攻击时,给定的区域是否可能被击中。
输入
输入中有多组测试数据。每组测试数据的第一行包含四个空格分隔的整数A、B和C和N,(-2*10^9<=A, B, C<=2*10^9, 1 <=N<=10^6),表示直线方程的参数以及目标矩形区域的数量,保证A^2+B^2>0。接下来有N行数据,每行包含8个空格分隔的整数“x1 y1 x2 y2 x3 y3 x4 y4”,表示目标四边形区域的定点坐标。
输出
对每组测试数据所代表的区域,若能够击中,则中单独的行中输出1,否则输出-1。
样例输入
0 1 0 1
-1 0 -1 0 1 0 1 0
1 -1 0 2
0 0 1 0 1 1 0 1
1 2 3 4 5 6 7 8
样例输出
1
1
-1
下面来看具体的代码
import java.util.Scanner;
public class chinamobile {
//判断直线和四边形是否相交
private static boolean isAttack(int A,int B,int C,int[] pos){
//其实是任意的两个以上同时等于0则认为是受攻击的
//处理特殊的情况
int zeroCount = 0;
if((A*pos[0] + B*pos[1] + C) == 0)zeroCount++;
if((A*pos[2] + B*pos[3] + C) == 0)zeroCount++;
if((A*pos[4] + B*pos[5] + C) == 0)zeroCount++;
if((A*pos[6] + B*pos[7] + C) == 0)zeroCount++;
if(zeroCount >= 2)return true;
boolean flag1 = (A*pos[0] + B*pos[1] + C) > 0?true:false;
boolean flag2 = (A*pos[2] + B*pos[3] + C) > 0?true:false;
boolean flag3 = (A*pos[4] + B*pos[5] + C) > 0?true:false;
boolean flag4 = (A*pos[6] + B*pos[7] + C) > 0?true:false;
if(flag1 == flag2&& flag2 == flag3 && flag3 == flag4)return false;
return true;
}
public static void main(String[] args){
Scanner sc = new Scanner(System.in);
while(true){
int A = sc.nextInt();
int B = sc.nextInt();
int C = sc.nextInt();
int N = sc.nextInt();
int[] pos = new int[8];
for(int m = 0;m<8;m++){
pos[m] = 0;
}
StringBuilder sb = new StringBuilder();
for(int i = 0;i<N;i++){ //每一行有4个坐标
pos[0] = sc.nextInt();
pos[1] = sc.nextInt();
pos[2] = sc.nextInt();
pos[3] = sc.nextInt();
pos[4] = sc.nextInt();
pos[5] = sc.nextInt();
pos[6] = sc.nextInt();
pos[7] = sc.nextInt();
if(isAttack(A,B,C,pos)){
sb.append("1").append("\n");
}else{
sb.append("-1").append("\n");
}
}
System.out.println(sb.toString().trim());
}
}
}