ZOJ1081:Points Within——题解

http://acm.zju.edu.cn/onlinejudge/showProblem.do?problemCode=1081

题目大意:给定一个点数为 n 的多边形,点按照顺序给出,再给出 m 个点,询问每个点是否在多边形内。

——————————————————————————————

计算几何开荒期,所以都算是板子吧……既然是板子那么题解自然也都是集网上之大成。

所以以后也就不多说了。正式往下看题解吧。

——————————————————————————————

这是一道求点是否在一个多边形内的题。

对这道题我们有两种算法,第二种太麻烦了就不讲了。

第一种为射线法:即我们有一个点,向左(右)水平做一道射线,求出射线与四边形交点个数,如果个数为奇数则在这里面。

但是如果交在线段端点上时我们需要规定交在边的下端点统计进答案或是交在边的上端点统计进答案(也就是保证一个点要么都被统计要么都不被统计)。

判断端点序号的坐标上下关系用叉乘,顺便可以判断该点是否在边上。

#include<cstdio>
#include<queue>
#include<cctype>
#include<cstring>
#include<vector>
#include<algorithm>
using namespace std;
typedef long long ll;
const int M=500010;
const int N=1000010;
const int INF=10*N;
inline int read(){
    int X=0,w=0;char ch=0;
    while(!isdigit(ch)){w|=ch==‘-‘;ch=getchar();}
    while(isdigit(ch))X=(X<<3)+(X<<1)+(ch^48),ch=getchar();
    return w?-X:X;
}
struct point{//既是向量又是点
    int x;
    int y;
}q[N],p;
int n,m,cnt;
inline point getmag(point a,point b){
    point s;
    s.x=b.x-a.x;s.y=b.y-a.y;
    return s;
}
inline int multiX(point a,point b){
    return a.x*b.y-b.x*a.y;
}
inline int multiP(point a,point b){
    return a.x*b.x+a.y*b.y;
}
bool pan(){
    int sum=0;
    for(int i=1;i<=n;i++){
    int d=multiX(getmag(p,q[i]),getmag(p,q[i%n+1]));
    if(!d){//三点共线
        if(multiP(getmag(p,q[i]),getmag(p,q[i%n+1]))<=0)return 1;//是否在线段上
    }
    int d1=q[i].y-p.y;
    int d2=q[i%n+1].y-p.y;
    if(d>0&&d1>=0&&d2<0)sum++;
    if(d<0&&d1<0&&d2>=0)sum++;
    }
    if(sum%2)return 1;
    return 0;
}
int main(){
    while(scanf("%d",&n)!=EOF&&n){
    m=read();
    cnt++;
    if(cnt!=1)putchar(‘\n‘);
    for(int i=1;i<=n;i++){
        q[i].x=read();
        q[i].y=read();
    }
    printf("Problem %d:\n",cnt);
    for(int i=1;i<=m;i++){
        p.x=read();
        p.y=read();
        if(pan())puts("Within");
        else puts("Outside");
    }
    }
    return 0;
}
时间: 2025-01-13 19:38:16

ZOJ1081:Points Within——题解的相关文章

ZOJ1081 Points Within

PS: 判断点是否在多边形内,用的绕圈法,具体参见刘汝佳的训练指南. #include <iostream> #include <cstdio> #include <cstring> #include <algorithm> #include <vector> #include <cmath> using namespace std; struct point { int x, y; point(double x=0, double

ZOJ1081 Points Within 点和多边形的位置关系

ZOJ1081 给一个点和一个多边形 判断点在多边形内(边上)还是在多边形外 在多边形外的点引一条射线必然穿过多边形的两条边 而在多边形内的点则不一定. 当然凹多边形有特殊情况 但是总能找到对应位置关系的边来抵消 #include<iostream> #include<stdio.h> #include<stdlib.h> #include<string.h> #include<math.h> #include<algorithm>

题解 CF576C 【Points on Plane】

题解 CF576C [Points on Plane] 一道很好的思维题. 传送门 我们看这个曼哈顿距离,显然如果有一边是按顺序排列的,显然是最优的,那另一边怎么办呢? 假如你正在\(ioi\)赛场上,此时遇到一个\(n\le 10^6\)的题目,你现在发现自己的排列最坏情况是\(O(n^2)\)的,你怎么办? 可以莫队优化! 于是复杂度降到了\(O(n\sqrt{n})\). 那么我们回来看,假设点是按\(x\)轴为关键字排序的,那么\(x\)方向产生的贡献最多是\(n\)的. 那么,算上\(

LeetCode-Max Points On a Line题解

一. 题意描述 Given n points on a 2D plane, find the maximum number of points that lie on the same straight line. 二. 题目分析 看到这道题想到的第一种方法是暴力枚举法,时间复杂度为O(n3),显然是不够好的. 于是我们需要进行一些优化,注意到对于一条直线上的任意两点,他们连线的斜率是相同的.于是我们可以算出指定点到其他所有点的斜率,先使得包含指定点的直线上点数最多,这个过程中可以建立斜率和直线

Codeforces 1140F Extending Set of Points 线段树 + 按秩合并并查集 (看题解)

Extending Set of Points 我们能发现, 如果把x轴y轴看成点, 那么答案就是在各个连通块里面的x轴的个数乘以y轴的个数之和. 然后就变成了一个并查集的问题, 但是这个题目里面有撤销的操作, 所以我们要把加入和撤销操作变成 这个点影响(L , R)之间的询问, 然后把它丢到线段树里面分成log段, 然后我们dfs一遍线段树, 用按秩合并并查集取维护, 回溯的时候将并查集撤销. #include<bits/stdc++.h> #define LL long long #def

POJ3090:Visible Lattice Points——题解

http://poj.org/problem?id=3090 题目大意:你站在(0,0)的点上看向第一向限的点,点和点会互相阻挡,问最多看到多少点. 很容易想到,我们能看到的点,它的横纵坐标一定是互质的,那么怎么求呢? 首先我们要知道一个东西叫做法雷级数: F1:0/1 1/1 F2:0/1 1/2 1/1 F3:0/1 1/3 1/2 2/3 1/1 F4:0/1 1/4 1/3 1/2 2/3 3/4 1/1 F5:0/1 1/5 1/4 1/3 2/5 1/2 3/5 2/3 3/4 4/

牛多校1I Points Division(DP)题解

题意:n个点,分成两组A,B,如果点i在A中,那么贡献值\(a_i\),反之为\(b_i\). 现要求任意\(i \in A,j \in B\)不存在 \(x_i >= x_j\) 且 \(y_i <= y_j\),也就是说A中点不在B中点的右下方. 思路:https://blog.nowcoder.net/n/7205418146f3446eb0b1ecec8d2ab1da 代码: #include<cmath> #include<set> #include<m

CF251A Points on Line 题解 二分

题目链接:http://codeforces.com/problemset/problem/251/A 题目描述 一条直线上有 \(n\) 个点,他们的坐标分别是 \(x_1,x_2, \cdots ,x_n\) .没有两个点的坐标相同. 你可以从这些点中挑选出三个点,使得三个点的最大距离不超过 \(d\) . 请求出满足条件的三个点的方案数. 输入格式 输入的第一行包含两个整数 \(n\) 和 \(d\) ( \(1 \le n \le 10^5; 1 \le d \le 10^9\) ).

题解【CF1311F Moving Points】

\[ \texttt{Preface} \] 赛时,把 " 任意时刻 " 理解成 " 整数时刻 " 了,看起来一脸不可做的亚子,还各种推式子. 话说我为什么觉得 E 比 F 还难. \[ \texttt{Description} \] 一个坐标轴 \(OX\) 上有 \(n\) 个点,第 \(i\) 个点位于整数点 \(x_i\) ,速度为 \(v_i\) . 所有点以恒定的速度移动,在时刻 \(t\) ( \(t\) 可以是非整数),第 \(i\) 个点的坐标可以