Codeforces166B Polygons(凸包判断)

题目链接:http://codeforces.com/problemset/problem/166/B


有点麻烦的叉乘+二分判断法:http://blog.csdn.net/xuh723/article/details/22337441


B. Polygons
time limit per test
2 seconds
memory limit per test
256 megabytes
input
standard input
output
standard output

You've got another geometrical task. You are given two non-degenerate polygons A and B as vertex coordinates. Polygon A is strictly convex. Polygon B is an arbitrary polygon without any self-intersections and self-touches. The vertices of both polygons are given in the clockwise order. For each polygon no three consecutively following vertices are located on the same straight line.

Your task is to check whether polygon B is positioned strictly inside polygon A. It means that any point of polygon B should be strictly inside polygon A. "Strictly" means that the vertex of polygon B cannot lie on the side of the polygon A.

Input

The first line contains the only integer n (3 ≤ n ≤ 105) — the number of vertices of polygon A. Then n lines contain pairs of integersxi, yi (|xi|, |yi| ≤ 109) — coordinates of the i-th vertex of polygon A. The vertices are given in the clockwise order.

The next line contains a single integer m (3 ≤ m ≤ 2·104) — the number of vertices of polygon B. Then following m lines contain pairs of integers xj, yj (|xj|, |yj| ≤ 109) — the coordinates of the j-th vertex of polygon B. The vertices are given in the clockwise order.

The coordinates of the polygon's vertices are separated by a single space. It is guaranteed that polygons A and B are non-degenerate, that polygon A is strictly convex, that polygon B has no self-intersections and self-touches and also for each polygon no three consecutively following vertices are located on the same straight line.

Output

Print on the only line the answer to the problem — if polygon B is strictly inside polygon A, print "YES", otherwise print "NO" (without the quotes).

Sample test(s)
input
6
-2 1
0 3
3 3
4 1
3 -2
2 -2
4
0 1
2 2
3 1
1 0
output
YES
input
5
1 2
4 2
3 -3
-2 -2
-2 1
4
0 1
1 2
4 1
2 -1
output
NO
input
5
-1 2
2 3
4 1
3 -2
0 -3
5
1 0
1 1
3 1
5 -1
2 -1
output
NO

题意:给出两个多边形A,B,保证A是一个凸多边形,判断B是否完全包含在A内。


先将所有的点都存在一个数组p中,然后求出凸包

然后二分判断多边形B中的点是否在凸包上,如果在凸包上则说明B没有完全包含在A内,输出NO。如果凸包上没有多边形B上的点,则输出YES。

(代码中二分用了algorithm中的lower_bound)

(用的Andrew求凸包,没有任何细节和注意事项- -)


#include <iostream>
#include <cstdio>
#include <cstring>
#include <string>
#include <algorithm>
#include <cmath>
using namespace std;
#define INF 0x3f3f3f3f
#define eps 1e-8

struct point
{
       double x,y;
       point(){}
       point(double _x,double _y)
       {
                    x=_x;y=_y;
       }
       point operator - (const point &b) const
       {
             return point(x-b.x,y-b.y);
       }
       bool operator < (const point &b) const
       {
            return x<b.x||x==b.x&&y<b.y;
       }
}res[120005],p[120005],pb[20005];

int na,nb,n;

int dcmp(double x)
{
    return (x>eps)-(x<-eps);
}

double cross(point a,point b)
{
       return a.x*b.y-b.x*a.y;
}

int andrew()
{
    sort(p,p+n);
    int m=0;
    for (int i=0;i<n;i++)
    {
        while (m>1&&cross(res[m-1]-res[m-2],p[i]-res[m-2])<0) --m;
        res[m++]=p[i];
    }
    int k=m;
    for (int i=n-2;i>=0;--i)
    {
        while (m>k&&cross(res[m-1]-res[m-2],p[i]-res[m-2])<0) --m;
        res[m++]=p[i];
    }
    if (m>1) --m;
    return m;
}

int main()
{
    while (scanf("%d",&na)!=EOF)
    {
          for (int i=0;i<na;i++)
          {
              scanf("%lf%lf",&p[i].x,&p[i].y);
          }
          scanf("%d",&nb);
          n=na+nb;
          for (int i=na;i<n;i++)
          {
              scanf("%lf%lf",&p[i].x,&p[i].y);
              pb[i-na]=p[i];
          }
          int m=andrew();
          bool flag=1;
          sort(pb,pb+nb);
          for (int i=0;i<m;i++)
          {
              int tmp=lower_bound(pb,pb+nb,res[i])-pb;//返回第一个大于等于res[i]的pb的下标
              if (dcmp(pb[tmp].x-res[i].x)==0&&dcmp(pb[tmp].y-res[i].y)==0) {flag=0;break;}//如果等于pb则说明B没有完全包含在A内,退出循环
          }
          if (flag==1) printf("YES\n");else printf("NO\n");
    }
    return 0;
}



  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值