zoukankan      html  css  js  c++  java
  • 计算几何基础与应用:HDU 1348&&ZOJ 1648&&POJ 2398&&ZOJ 1010

    首先声明叉积在计算几何是基本用法!!他的奶名就叫做向量积!!(好熟悉的称呼)

    那么叉积主要注意方向问题:他是以前面的向量为起点转向另外那个向量的角度!!

    Wall  HDU 1348

    一道模板题!!(凸包问题)

    三步骤:排序,再排序,再是重点进行判断!!!

    先进行排序,从小到大找出最左下角的一个坐标!

    之后以这个坐标找出每个点的极角(用个三角公式atan2(y,x))

    之后以三点为核心进行判断!!!

    如果第三点在前两点连线的左边可以,不然回溯再进行判断!!

    具体参见:http://hi.baidu.com/nicker2010/item/757c4350688a86a3adc857ed

     1 #include<iostream>
     2 #include<stdio.h>
     3 #include<algorithm>
     4 #include<math.h>
     5 #define PI 3.14159265
     6 using namespace std;
     7 struct line
     8 {
     9     double x;
    10     double y;
    11     double angle;
    12 }a[1010],b[1010];
    13 double comp(line i,line j)
    14 {
    15     if(i.y==j.y)
    16         return i.x<j.x;
    17     return i.y<j.y;
    18 }
    19 double comp1(line i,line j)
    20 {
    21     if(i.angle==j.angle)
    22     {
    23         if(i.x==j.x)
    24             return i.y>j.y;
    25         return i.x>j.x;
    26     }
    27     return i.angle<j.angle;
    28 }
    29 double add(line i,line j,line z)
    30 {
    31     double a1=z.y-i.y;
    32     double a2=z.x-i.x;
    33     double a3=z.y-j.y;
    34     double a4=z.x-j.x;
    35     return a2*a3-a1*a4;
    36 }
    37 double abb(line i,line j)
    38 {
    39     return sqrt((i.y-j.y)*(i.y-j.y)+(i.x-j.x)*(i.x-j.x));
    40 }
    41 int main()
    42 {
    43     int t,n,i,j,top;
    44     double m,len;
    45     scanf("%d",&t);
    46     while(t--)
    47     {
    48         scanf("%d%lf",&n,&m);
    49         for(i=1;i<=n;i++)
    50             scanf("%lf%lf",&a[i].x,&a[i].y);
    51         sort(a+1,a+n+1,comp);//排序
    52         for(i=2;i<=n;i++)
    53             a[i].angle=atan2(a[i].y-a[1].y,a[i].x-a[1].x);//求极角
    54         sort(a+2,a+1+n,comp1);//再排序,第一个坐标不用排序
    55         b[1]=a[1];//***********
    56         b[2]=a[2];
    57         b[3]=a[3];
    58         top=4;
    59         for(i=4;i<=n;i++)
    60         {
    61             while(top>3&&add(b[top-2],b[top-1],a[i])<=0)//以三点进行判断
    62                 top--;
    63             b[top++]=a[i];
    64         }//**************核心
    65         len=abb(b[1],b[top-1]);
    66         for(i=2;i<top;i++)
    67             len+=abb(b[i],b[i-1]);
    68         len+=2*PI*m;
    69         printf("%.0lf
    ",len);
    70         if(t)
    71             printf("
    ");
    72     }
    73     return 0;
    74 }

    Circuit Board ZOJ 1648

    怎么用叉积判断两线段是否相交!!

    有一种方法叫做:跨立实验

    如果两线段相交,则两线段必然相互跨立对方。

    P1P2跨立Q1Q2 ,则矢量 ( P1 - Q1 ) ( P2 - Q1 )位于矢量( Q2 - Q1 ) 的两侧,

    ( P1 - Q1 ) × ( Q2 - Q1 ) * ( P2 - Q1 ) × ( Q2 - Q1 ) < 0

    那么就好做了:

     1 #include<iostream>
     2 #include<algorithm>
     3 #include<stdio.h>
     4 #include<math.h>
     5 using namespace std;
     6 struct line
     7 {
     8     double x;
     9     double y;
    10 }a[2005],b[2005];
    11 double abb(double x1,double y1,double x2,double y2)
    12 {
    13     return x1*y2-y1*x2;
    14 }
    15 bool add(double x1,double y1,double x2,double y2,double x3,double y3,double x4,double y4)
    16 {
    17     double temp1,temp2,temp3,temp4;
    18     temp1=abb(x1-x3,y1-y3,x4-x3,y4-y3);
    19     temp2=abb(x4-x3,y4-y3,x2-x3,y2-y3);
    20     if(temp1*temp2>0)
    21         return true;
    22     return false;
    23 }
    24 int main()
    25 {
    26     int i,j,n,d;
    27     while(scanf("%d",&n)!=EOF)
    28     {
    29         for(i=1;i<=n;i++)
    30             scanf("%lf%lf%lf%lf",&a[i].x,&a[i].y,&b[i].x,&b[i].y);
    31         d=0;
    32         for(i=1;i<=n-1;i++)
    33             {
    34                 for(j=i+1;j<=n;j++)
    35         {
    36             if(add(a[i].x,a[i].y,b[i].x,b[i].y,a[j].x,a[j].y,b[j].x,b[j].y))
    37             {
    38                 d=1;
    39                 break;
    40             }
    41         }
    42         if(d==1)
    43             break;
    44             }
    45         if(d==1)
    46             printf("burned!
    ");
    47         else
    48             printf("ok!
    ");
    49     }
    50     return 0;
    51 }//坐标表示可用结构体

     Toy Storage  POJ 2398

    考点是:一个点是否在一个多边形内外!

    但是这个题目的构造直接判断点在两条线段里面还是外面就可以了。。。

    其实你都可以

    把这个点做平行于x轴的射线,直接解方程得出x判断大小就可以了。。。

    基本就是用叉积判断正负(也就是叉积的方向)。。。

     1 #include<iostream>
     2 #include<stdio.h>
     3 #include<algorithm>
     4 #include<string.h>
     5 using namespace std;
     6 int b[10005],n,y2,y1,x1,x2,x12,y12,m,i,c,x;
     7 struct line
     8 {
     9     int x1;
    10     int x2;
    11 }a[1005];
    12 int comp1(line i,line j)
    13 {
    14     return i.x1<j.x1;
    15 }
    16 double abb(double x,double y,double x1,double y1)
    17 {
    18     return x*y1-x1*y;
    19 }
    20 int add(double x,int y,int i)
    21 {
    22     double d,d1;
    23     d=abb(a[i].x1-x,y1-y,a[i].x2-x,y2-y);
    24     if(i==1)
    25     {
    26         if(d<0)
    27         {
    28             b[i]++;
    29             return 1;
    30         }
    31     }
    32     else if(i==n+1)
    33     {
    34         if(d>0)
    35         {
    36             b[i]++;
    37             return 1;
    38         }
    39     }
    40     else
    41     {
    42         d1=abb(a[i-1].x1-x,y1-y,a[i-1].x2-x,y2-y);
    43         if(d<0&&d1>0)
    44         {
    45             b[i]++;
    46             return 1;
    47         }
    48     }
    49     return 0;
    50 }
    51 int main()
    52 {
    53     while(scanf("%d",&n)!=EOF)
    54     {
    55         if(n==0)
    56             break;
    57         memset(b,0,sizeof(b));
    58         scanf("%d%d%d%d%d",&m,&x1,&y1,&x2,&y2);
    59         for(i=1;i<=n;i++)
    60             scanf("%d%d",&a[i].x1,&a[i].x2);
    61         sort(a+1,a+1+n,comp1);
    62         a[n+1].x1=a[n].x1;a[n+1].x2=a[n].x2;
    63         while(m--)
    64         {
    65             scanf("%d%d",&x12,&y12);
    66             for(i=1;i<=n+1;i++)
    67                 if(add(x12,y12,i))
    68                     break;
    69         }
    70         sort(b+1,b+1+n+1);
    71         int d=0;
    72         c=1;x=0;
    73         printf("Box
    ");
    74         for(i=1;i<=n+1;i++)//*******输出形式搞了很久
    75         {
    76             if(b[i]!=0)
    77             {
    78                 c=b[i];
    79                 while(b[i]==c&&i<=n+1)
    80             {
    81                 if(d==0)
    82                 printf("%d: ",b[i]);
    83                 d=1;
    84                 i++;
    85                 x++;
    86             }
    87             printf("%d
    ",x);
    88             x=0;
    89             d=0;
    90             i--;
    91             }
    92         }//**************
    93     }
    94     return 0;
    95 }

     Area  ZOJ 1010

    一道简单的题目。。。

    主要判断是不是多边形!!!

    具体参见:http://blog.sina.com.cn/s/blog_5ced353d0100b1xd.html

     1 #include<iostream>
     2 #include<algorithm>
     3 #include<stdio.h>
     4 using namespace std;
     5 double a[1005],b[1005];
     6 double abb(int i,int j,int k)
     7 {
     8     return (a[j]-a[i])*(b[j]-b[k])-(a[j]-a[k])*(b[j]-b[i]);
     9 }
    10 int add(int x1,int y1,int x2,int y2)
    11 {
    12     if(abb(x2,x1,y1)*abb(y2,x1,y1)>0)//两次判断
    13         return 0;
    14     if(abb(x1,x2,y2)*abb(y1,x2,y2)>0)
    15         return 0;
    16   return 1;
    17 }
    18 int main()
    19 {
    20     int w=0,d,i,j,n;
    21     double s;
    22     while(scanf("%d",&n)!=EOF&&n)
    23     {
    24         if(w)
    25             printf("
    ");
    26         for(i=0;i<n;i++)
    27             scanf("%lf%lf",&a[i],&b[i]);
    28         if(n<3)
    29         {
    30             printf("Figure %d: Impossible
    ",++w);
    31             continue;
    32         }
    33         d=0;
    34         for(i=1;i<=n-1;i++)
    35         {
    36             for(j=1;j<=i-2;j++)
    37                 if(add(i,i-1,j,j-1))//只需判断不相邻的边是否相交
    38                     {d=1;break;}
    39             if(d==1)
    40                 break;
    41         }
    42         if(d==1)
    43         {printf("Figure %d: Impossible
    ",++w);continue;}
    44         for(i=2;i<n-1;i++)
    45             if(add(0,n-1,i,i-1))
    46                 {d=1;break;}
    47         if(d==1)
    48         {printf("Figure %d: Impossible
    ",++w);continue;}
    49         s=0;
    50         for(i=1;i<n;i++)
    51             s+=a[i-1]*b[i]-a[i]*b[i-1];
    52         s+=a[n-1]*b[0]-a[0]*b[n-1];
    53         if(s<0)
    54             s*=-1;
    55         printf("Figure %d: %.2lf
    ",++w,s/2);
    56     }
    57     return 0;
    58 }
  • 相关阅读:
    HBase导入数据同时与Phoenix实现同步映射
    Hive导入数据到HBase,再与Phoenix映射同步
    CDH5.16.1离线集成Phoenix
    设计原则学习笔记
    Maven安装配置
    SpringBoot之Mybatis操作中使用Redis做缓存
    Linux服务器防火墙白名单设置
    Linux查看端口占用情况,并强制释放占用的端口
    shell脚本切割tomcat日志文件
    mysql读写分离
  • 原文地址:https://www.cnblogs.com/tt123/p/3273100.html
Copyright © 2011-2022 走看看