zoukankan      html  css  js  c++  java
  • poj4048

       高精度的极角计算是种很实用的算法。由于计算机采用64位的二进制来表示实数,不管再怎么样,总是会带来误差的。所以采用整数计算才能做到精确无误,当然毕竟角度值可以是任意实数,所以我说的整数计算,只是把角度值采用两个整数(类似于数学里一个向量)给映射出来(通过象限等的限制),准确的表达出角度的大小关系。代码中小于符号重载是核心,请读者仔细阅读。

         题目抽象大意:在一个二维平面坐标中,有n条线段(每个点用(x1,y1),(x2,y2)表示两个端点([-10000,10000]*[-10000,10000]范围内)),给定某个点(x0,y0),以这个点为起点,求以某个方向引出一条射线能交到的最大线段数。

         先不管这个题,我们来看另外一个情景:某个电影院门口有个光门,如果有人经过那个门口时就会立即触发光门记录一个时间值,若是离开电影院标记时间属性为out,若是进入电影就标记时间属性为in。求电影院里最大人流量。

        其实把光门记录的时间按从小到大排序,时间值相同时out属性的时间值排在in后面,我们将所有时间值属性按照时间值从小到大遍历一遍,in加1,out减1,中间出现的最大数字即为所求。

         所以本题最重要的是要将线段的端点进行排序。如果排序解决了,按照上面的方法求解就行。

         一般的线段,我们可以按照两端点与(x0,y0)作差形成两个向量(x正半轴到这个向量的到角的大小就是这个向量的“时间值”),利用外积的正负性断定这两个个向量的in属性和out属性。为了讨论方便,我们先把原点平移到(x0,y0)。

         一类比较特殊的线段就是经过原点的线段(不管沿哪个方向引射线都会相交);另一类就是这个时间值发生冲突的线段,如某个线段in点在第四象限,out点在在第一象限(这类似的点),这种情况下,我们就需要将这跟线段拆分成两段!这就保证每个向量能唯一指示一个角度值(“时间值”)。0和360度是重合的,我们可以强制(infinity,0)向量指示360度(infinity为一个大于10000的数)。

      1 /*
      2   Name: poj4048  整点计算极角 
      3   Copyright: 
      4   Author:   Karlvin (指导老师:朱国进 dhu) 
      5   Date: 23/05/12 16:43
      6   Description: 
      7 */
      8 #include <iostream>
      9 #include <set>
     10 #include <cstdio>
     11 #include <algorithm>
     12 using namespace std;
     13 const int size = 10010;
     14 const int inf = 2000010000;
     15 struct point{
     16     int x, y;
     17     int no;  //调试时用的变量,无实际意义 
     18     bool tail;
     19     point(int a = 0, int b = 0,int cn=0,bool t=false){x = a; no = cn; y = b; tail = t;}
     20     point operator =(point t) { x=t.x; y=t.y; no=t.no; tail=t.tail; return *this; }
     21     void print(){ printf("( %d, %d) %d, %d\t",x,y,no,tail); }
     22     friend bool operator < (point p1, point p2){ //按照“到角”大小排序,角度相等时尾节点的角度排在后面 
     23         if(p1.y == 0 && p1.x > 0)
     24         {       if(p1.x >= inf)
     25                      return false;
     26                 if(p2.y==0 && p2.x < inf && p2.x > 0)
     27                 {          if(!(p1.tail^p2.tail)) return false;
     28                            return !p1.tail;   }
     29                 return true;   }
     30         else if(p2.y == 0 && p2.x > 0)
     31         {       if(p2.x >= inf)
     32                      return true;
     33                 return false;   }
     34         if(p1.y * p2.y < 0)
     35             return p1.y > p2.y;
     36         int t = p1.x * p2.y - p1.y * p2.x;
     37         if(t != 0)  return t > 0;
     38         if(!(p1.tail^p2.tail)) 
     39                 return false;
     40         return !p1.tail;
     41     }
     42 };
     43 point start[size];
     44 point end[size];
     45 int xx1[size];
     46 int xx2[size];
     47 int yy1[size];
     48 int yy2[size];
     49 int pxp(int &x1,int &y1,int &x2,int &y2)  //若X积小于0 
     50 {
     51     int ans = x1*y2-x2*y1;
     52     if(ans < 0)
     53     {      swap(x1,x2);
     54            swap(y1,y2); }
     55     return ans;
     56 }
     57 int base,index;
     58 bool cross_x(int x1,int y1,int x2,int y2)  //穿越x正半轴将线段拆分 
     59 {
     60      if(y2 >= 0 && y1 < 0) // 等价于 (x1,y1)X(0,1)  > 0 && (0,1)X(x2,y2) >=0
     61      {        start[index] = point(1,0,index,false);
     62               end[index] = point(x2,y2,index,true);
     63               index++;
     64               start[index] = point(x1,y1,index,false);
     65               end[index] = point(inf,0,index,true);
     66               index++;
     67               return true; }
     68      return false;
     69 }
     70               
     71 int main(){
     72     int cases=0;
     73     cin>>cases;
     74     while(cases--)
     75     {
     76         int n;
     77         cin >> n;
     78         base = 0, index = 0;
     79         int x1,y1,x2,y2,ans;
     80         bool flag = true;
     81         for(int i=0;i<n;i++)
     82                 scanf("%d%d%d%d",&xx1[i],&yy1[i],&xx2[i],&yy2[i]);
     83         int tx,ty;
     84         cin>>tx>>ty;
     85         for (int i = 0; i < n; i++){
     86             x1 = xx1[i]-tx;  x2 = xx2[i]-tx;
     87             y1 = yy1[i]-ty;  y2 = yy2[i]-ty;
     88             ans = pxp(x1,y1,x2,y2);
     89             flag = false;
     90             if(0 == ans && (y1*y2<= 0 || x1*x2 <= 0) ){ //经过原点: 叉积为0,且两点不在坐标轴的同一侧 
     91                 base++;
     92             }else{
     93                   if(ans != 0 && cross_x(x1,y1,x2,y2))
     94                          flag = true;
     95                   if(!flag)
     96                   {     start[index] = point(x1,y1,index,false);
     97                         end[index] = point(x2,y2,index,true);
     98                         index++;    }
     99             }
    100         }
    101         /*                          //辅助输出 
    102         cout<<"index = "<<index<<endl;
    103         cout<<"base = "<<base<<endl;
    104         for(int i = 0; i < index; i++)
    105         {       start[i].print();
    106                 end[i].print();
    107                 cout<<endl;  }
    108         */
    109         multiset<point> group;
    110         for(int i=0; i<index; i++)
    111         {       group.insert(start[i]);
    112                 group.insert(end[i]); }
    113         multiset<point>::iterator it = group.begin();
    114         ans = 0;
    115         int max = 0;
    116         point t;
    117         while(it != group.end())
    118         {    //    t = *it;  t.print(); cout<<endl;  //辅助输出 
    119                  if(it->tail)
    120                      max--;
    121                  else  max++;
    122                  if(max > ans)
    123                         ans = max;
    124                  it++; }
    125         printf("%d\n",ans+base);
    126     }
    127     system("pause");
    128     return 0;
    129 }
    View Code
  • 相关阅读:
    奇妙的html 和 Css【关于html、Css 开发中重要的细节和一些小奇怪现象】
    JavaWeb项目img标签的图片无法加载的原因及解决方法
    批量建堆(二叉堆【完全二叉堆】)~~批量建堆
    为什么要面向对象(转)
    不从0开始序列的matlab卷积实验
    虚数、傅里叶变换中负频率的意义
    运动的6个自由度
    转载:关于Ω, f, w的前世今生
    利用matplotlib画用于机器学习的K线图练手任务
    信息工程学院——电子信息工程到底学什么?
  • 原文地址:https://www.cnblogs.com/karlvin/p/poj4048.html
Copyright © 2011-2022 走看看