zoukankan      html  css  js  c++  java
  • [Swust OJ 567]--老虎在不在笼子里(凸包问题)

    题目链接:http://acm.swust.edu.cn/problem/567/

    Time limit(ms): 1000      Memory limit(kb): 65535
     
    一只老虎自从看了<越狱>以来,脾气就比较暴躁,而且变得神神秘密的.一天管理员发现老虎不见了,这下他可急坏了,赶紧通知了110.幸好这只老虎身上装了GPS,所以还有希望找到他. 
    你的任务就是通过GPS给出的老虎的坐标和笼子的坐标来让电脑计算出老虎的位置,是躲在洞里了,还是跑到外面去了.
    Description
    输入数据有N+2行: 
    第一行是一个数据N(0<=N<=12),代表了笼子的坐标X,Y的个数(X,Y都在INT范围内); 
    第二到N+1行是N个坐标X,Y,依次按从下逆时针的顺序来给出的. 
    最后一行是老虎的坐标X,Y; 

    注:只有一组测试数据,输入的都是整数,笼子一定是凸多边形,而且老虎也不会出现在笼子边界上 


    三角形的面积可以用向量的外积来计算,那么多边形是N个三角形,那么就可以。。。。。 
    Input
    如果老虎还在笼子里,输入"YES",否则是"NO";
    Output
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    4
    0 0
    1 0
    1 1
    0 1
    0.5 0.5
     
    6
    1 -1
    2 0
    1 1
    -1 1
    -2 0
    -1 -1
    3 3
    Sample Input
    1
    2
    YES
    NO
    Sample Output
     
    解题思路:这道题看上去可能会以为是一个很坑的数学问题,但是仔细读题就会发现
         这道题其实就是比较笼子构成的凸包面积,和加入老虎坐标新的点集构成的新凸包的面积
         是否相等的题,相等即老虎在笼子内,反之亦然~~
         关于凸包的问题,可以戳戳这里:http://www.cnblogs.com/zyxStar/p/4540984.html
     
    代码如下:
     1 //只需要判断加入该点凸包面积,和笼子构成凸包面积是否相等即可
     2 
     3 #include<iostream>
     4 #include<cstdio>
     5 #include<algorithm>
     6 #include<stack>
     7 #include<cmath>
     8 using namespace std;
     9 struct node{
    10     double x, y;
    11 }point[110], tiger[101], posA, posB, tmp;//posB老虎基准量
    12 
    13 double dis(node a, node b){
    14     return pow((a.x - b.y), 2) + pow((a.y - b.y), 2);
    15 }
    16 
    17 //按点集分布排序,利用向量平行关系判断
    18 bool cmp(node a, node b){
    19     double povit = (a.x - posA.x)*(b.y - posA.y) - (b.x - posA.x)*(a.y - posA.y);
    20     if (povit > 0 || !povit && (dis(a, posA) < dis(b, posA)))
    21         return true;
    22     return false;
    23 }
    24 
    25 //当前点是否在点集左侧,利用叉乘比较3个点两条线的斜率关系
    26 bool turn_left(node p1, node p2, node p3){
    27     return (p2.x*p1.y + p3.x*p2.y + p1.x*p3.y - p3.x*p1.y - p1.x*p2.y - p2.x*p3.y) > 0 ? true : false;
    28 }
    29 
    30 int main(){
    31     int i, sign1, sign2, n;
    32     double area1, area2;
    33     cin >> n;
    34     for (i = 0; i < n; i++){
    35         cin >> point[i].x >> point[i].y;
    36         tiger[i].x = point[i].x;
    37         tiger[i].y = point[i].y;
    38     }
    39     cin >> tiger[i].x >> tiger[i].y;//老虎坐标
    40     stack<node> Q;
    41     sign1 = 0;
    42     posA = posB = point[0];
    43     //分别找到笼子,加入老虎坐标 的点集的最左下的点
    44     for (i = 1; i < n + 1; i++){
    45         if (i<n){
    46             if (posA.y == point[i].y&&posA.x>point[i].x || point[i].y < posA.y){
    47                 posA = point[i];
    48                 sign1 = i;
    49             }
    50         }
    51         else{
    52             posB = posA;
    53             sign2 = sign1;
    54             if (posB.y == tiger[i].y&&posB.x>tiger[i].x || tiger[i].y < posB.y){
    55                 posB = tiger[i];
    56                 sign2 = i;
    57             }
    58         }
    59     }
    60     swap(point[0], point[sign1]);
    61     swap(tiger[0], tiger[sign2]);
    62     sort(point + 1, point + n, cmp);//利用叉乘按点集离散化,方便筛选构成图凸包有效的点
    63     sort(tiger + 1, tiger + n + 1, cmp);
    64     Q.push(tiger[0]), Q.push(tiger[1]), Q.push(tiger[2]);
    65 
    66     for (i = 3; i < n + 1; i++){
    67         while (!Q.empty()){
    68             tmp = Q.top();
    69             Q.pop();
    70             if (turn_left(tmp, Q.top(), tiger[i])){
    71                 Q.push(tmp);
    72                 break;
    73             }
    74         }
    75         Q.push(tiger[i]);
    76     }
    77     //由于给出笼子必为凸包,直接计算面积
    78     area1 = area2 = 0;
    79     tmp = point[n - 1];
    80     area1 += (posA.x*tmp.y - posA.y*tmp.x) / 2.0;
    81     for (i = n - 2; i >= 0; i--){
    82         area1 += (tmp.x*point[i].y - tmp.y*point[i].x) / 2.0;
    83         tmp = point[i];
    84     }
    85 
    86     tmp = Q.top(), Q.pop();
    87     area2 += (posA.x*tmp.y - posA.y*tmp.x) / 2.0;
    88     while (!Q.empty()){
    89         area2 += (tmp.x*Q.top().y - tmp.y*Q.top().x) / 2.0;
    90         tmp = Q.top();
    91         Q.pop();
    92     }
    93     printf("%s
    ", area1 == area2 ? "YES" : "NO");
    94     return 0;
    95 }
    View Code
     
  • 相关阅读:
    JavaScript之事件冒泡和事件捕获详细介绍
    jQuer配合CSS3实现背景图片动画
    jQuery中animate()的方法以及$("body").animate({"scrollTop":top})不被Firefox支持问题的解决
    JavaScript 运用之表单验证(正则)和控制输入长度。
    input[type=submit]以及数字日期在苹果手机上显示异常的处理
    webstorm 快捷键
    Bootstrap 折叠(Collapse)插件
    input输入内容时放大问题及处理
    省市二级联动(原生JS)
    Spring4.X——搭建
  • 原文地址:https://www.cnblogs.com/zyxStar/p/4572851.html
Copyright © 2011-2022 走看看