https://koitp.org/problem/POSITION_OF_POINT
求最后两个点,是在图形的外面,还是里面
换成了double,依然没有AC,只是从30 / 100提升到了90 / 100
换成BigInteger后AC了
import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.math.BigInteger;
/**
meng3.wei 2020.04.16
4
1 1
1 3
3 3
3 1
0 0
2 2
out
in
*/
public class 点的位置 {
static int Max_x=0;
static int Max_y=0;
public static void main(String[] args) throws Exception{
BufferedReader reader=new BufferedReader(new InputStreamReader(System.in));
int N=Integer.parseInt(reader.readLine());
Point[] points=new Point[N];
for (int i = 0; i <N ; i++) {
String[] line=reader.readLine().split(" ");
int x=Integer.parseInt(line[0]);
int y=Integer.parseInt(line[1]);
if(x>Max_x){Max_x=x;}
if(y>Max_y){Max_y=y;}
points[i]=new Point(x,y);
}
String[] line=reader.readLine().split(" ");
Point A=new Point(Integer.parseInt(line[0]),Integer.parseInt(line[1]));
line=reader.readLine().split(" ");
Point B=new Point(Integer.parseInt(line[0]),Integer.parseInt(line[1]));
System.out.println(process(points,A));
System.out.println(process(points,B));
reader.close();
}
static String process(Point[] points,Point C){
String result="out";
int m=0;
Point D=new Point(Max_x+97,Max_y+99);
for (int i = 0; i < points.length-1; i++) {
Point A=points[i];
Point B=points[i+1];
if(cross_check(A,B,C,D)==1){
m++;
}
}
Point A=points[0];
Point B=points[points.length-1];
if(cross_check(A,B,C,D)==1){
m++;
}
if(m%2==1){//奇数,点在里面
result="in";
}
return result;
}
static int cross_check(Point A,Point B,Point C,Point D){
int abc=direction(A,B,C);
int abd=direction(A,B,D);
int cda=direction(C,D,A);
int cdb=direction(C,D,B);
if(abc*abd <=0 && cda*cdb<=0){
//System.out.printf("ABCD相交 %d,%d->%d,%d %d,%d->%d,%d \n",A.x,A.y,B.x,B.y,C.x,C.y,D.x,D.y);
return 1;
}else{
//System.out.printf("ABCD不相交 %d,%d->%d,%d %d,%d->%d,%d \n",A.x,A.y,B.x,B.y,C.x,C.y,D.x,D.y);
return 0;
}
}
public static int direction(Point A,Point B,Point C){
int dxAB=B.x-A.x;
int dyAB=B.y-A.y;
int dxAC=C.x-A.x;
int dyAC=C.y-A.y;
int abc=BigInteger.valueOf(dxAB).multiply(BigInteger.valueOf(dyAC)).compareTo(
BigInteger.valueOf(dyAB).multiply(BigInteger.valueOf(dxAC))
);
if(abc>0){
return -1;//顺时针
}else if(abc<0){
return 1;//逆时针
}else{
if(A.x==B.x && A.y==B.y){
return 0;//A和B在一个点上
}
if(BigInteger.valueOf(dxAB).multiply(BigInteger.valueOf(dxAC)).compareTo(BigInteger.ZERO)<0 ||
BigInteger.valueOf(dyAB).multiply(BigInteger.valueOf(dyAC)).compareTo(BigInteger.ZERO)<0
){
return -1;//A在BC的中间,也就是AB和AC刚好接在一起
}else if(
BigInteger.valueOf(dxAB).multiply(BigInteger.valueOf(dxAB))
.add(
BigInteger.valueOf(dyAB).multiply(BigInteger.valueOf(dyAB))).compareTo(
BigInteger.valueOf(dxAC).multiply(BigInteger.valueOf(dxAC)).add(
BigInteger.valueOf(dyAC).multiply(BigInteger.valueOf(dyAC)))
)>=0
){//C在AB的中间
return 0;
}else {
return -1;
}
}
}
static class Point{
int x;
int y;
public Point(int parseInt, int parseInt1) {
this.x=parseInt;
this.y=parseInt1;
}
}
}
别人AC的代码,没看懂,mark一下
#include <cstdio>
#include <vector>
#define maxfunc(a,b)(a>b?a:b)
#define minfunc(a,b)(a<b?a:b)
using namespace std;
typedef struct point{
long x, y;
}Point;
typedef struct poligon{
int ptNums;
Point *ptlst;
}Poligon;
int n,cas;
int main(){
vector<Point> vpt;
vpt.reserve(100001);
scanf("%d", &n);
for (int i = 0; i < n; i++){
Point p;
scanf("%ld%ld", &p.x, &p.y);
vpt.push_back(p);
}
Poligon pol;
pol.ptNums = n;
pol.ptlst = &vpt[0];
Point testpt;
cas = 0;
while (scanf("%ld%ld", &testpt.x, &testpt.y) == 2)
{
int cnt = 0;
for (int i = 0; i < pol.ptNums; i++){
long x1, x2, y1, y2;
double tx, t;
x1 = pol.ptlst->x, y1 = pol.ptlst->y;
if (i == (n - 1)){
// next point is first point(0) if current is n-1
pol.ptlst -= (n - 1);
}
else pol.ptlst++; // go next point
x2 = pol.ptlst->x, y2 = pol.ptlst->y;
//tmp1 = maxfunc(y1, y2);
if (testpt.y >= maxfunc(y1, y2) || testpt.y <= minfunc(y1, y2)) continue;
t = (double)(testpt.y - y2) / (y1 - y2);
// tx is the cross point
tx = (double)x2 - t*(x2 - x1);
// only count the point at left of tx
if (testpt.x < tx) cnt++;
}
printf("%s\n", cnt % 2 == 0 ? "out" : "in");
if(++cas>1) break;
}
return 0;
}