zoukankan      html  css  js  c++  java
  • hdu 3629 Convex

    题意:给你N个点,让你选四个点组成凸多边形,求总的方法数

    详细解释:http://blog.sina.com.cn/s/blog_64675f540100ksug.html

      1 #include<iostream>
      2 #include<vector>
      3 #include<cstring>
      4 #include<cstdio>
      5 #include<cmath>
      6 #include<stdlib.h>
      7 #include<queue>
      8 #include<map>
      9 #include<algorithm>
     10 using namespace std;
     11 const double eps = 1e-12;
     12 const double pi = acos(-1.0);
     13 const double INF = 10001000;
     14 double sqr(double x){
     15     return x*x;
     16 }
     17 int cmp(double x){
     18     if(fabs(x)<eps) return 0;
     19     if(x>0) return 1;
     20     return -1;
     21 }
     22 struct point{
     23     double x,y;
     24     int index;
     25     point(){}
     26     point(double a,double b):x(a),y(b){}
     27     void input(){
     28         scanf("%lf%lf",&x,&y);
     29     }
     30     double angle() {
     31         return atan2(y, x);
     32     }
     33     friend point operator + (const point &a,const point &b){
     34         return point(a.x+b.x,a.y+b.y);
     35     }
     36     friend point operator - (const point &a,const point &b){
     37         return point(a.x-b.x,a.y-b.y);
     38     }
     39     friend bool operator == (const point &a,const point &b){
     40         return (cmp(a.x-b.x)==0)&&(cmp(a.y-b.y))==0;
     41     }
     42     friend point operator * (const point &a,double b){
     43         return point(a.x*b,a.y*b);
     44     }
     45     friend point operator / (const point &a,double b){
     46         return point(a.x/b,a.y/b);
     47     }
     48     friend double operator ^ (const point &a,const point &b)
     49     {
     50         return a.x*b.y - a.y*b.x;
     51     }
     52      double operator *(const point &b)const
     53     {
     54         return x*b.x + y*b.y;
     55     }
     56     double norm(){                              //向量的模长
     57         return sqrt(sqr(x)+sqr(y));
     58     }
     59 };
     60 
     61 double det(const point &a,const point &b){      //向量的叉集
     62     return a.x*b.y-a.y*b.x;
     63 }
     64 double dot(const point &a,const point &b){      //向量的点集
     65     return a.x*b.x+a.y*b.y;
     66 }
     67 double dot(const point &a,const point &b,const point &c){      //向量的点集ba 到bc
     68     return dot(a-b,c-b);
     69 }
     70 double dist(const point &a,const point &b){     //两点间的距离
     71     return (a-b).norm();
     72 }
     73 point rotate_point(const point &p,double A){    // 绕原点逆时针旋转 A(弧度)
     74     double tx=p.x,ty=p.y;
     75     return point(tx*cos(A)-ty*sin(A),tx*sin(A)+ty*cos(A));
     76 }
     77 //向量的旋转 //底边线段ab 绕a逆时针旋转角度A,b->b1,sinl是sinA的值。
     78 point rotate_point(double cosl,double sinl,point a, point b){
     79     b.x -= a.x; b.y -= a.y;
     80     point c;
     81     c.x = b.x * cosl - b.y * sinl + a.x;
     82     c.y = b.x * sinl + b.y * cosl + a.y;
     83    return c;
     84 }
     85 double xml(point x,point t1,point t2){    // 如果值为正,(t1-x)在(t2-x)的瞬时间方向
     86     return det((t1-x),(t2-x));
     87 }
     88 double area(point x,point y,point z){
     89     return (det(y-x,z-x));
     90 }
     91 struct line {
     92     point a,b;
     93     line(){}
     94     line(point x,point y):a(x),b(y){}
     95 };
     96 point P_chuizhi_line(point a,point l1,point l2)    // 求一个点,使得ac垂直于l1l2
     97 {
     98     point c;
     99     l2.x -= l1.x; l2.y -= l1.y;
    100     c.x = a.x - l1.x - l2.y + l1.x;
    101     c.y = a.y - l1.y + l2.x + l1.y;
    102     return c;
    103 }
    104 point P_To_seg(point P,line L)                  //点到线段 最近的一个点
    105 {
    106     point result;
    107     double t = ((P-L.a)*(L.b-L.a))/((L.b-L.a)*(L.b-L.a));
    108     if(t >= 0 && t <= 1)
    109     {
    110         result.x = L.a.x + (L.b.x - L.a.x)*t;
    111         result.y = L.a.y + (L.b.y - L.a.y)*t;
    112     }
    113     else
    114     {
    115         if(dist(P,L.a) < dist(P,L.b))
    116             result = L.a;
    117         else result = L.b;
    118     }
    119     return result;
    120 }
    121 double dis_p_to_line(point p,line l){         //点到直线的距离
    122     return fabs(area(p,l.a,l.b))/dist(l.a,l.b);
    123 }
    124 double dis_p_to_seg(point p,line l)            //点到线段的距离
    125 {
    126    return dist(p,P_To_seg(p,l));
    127 }
    128 double dis_pall_seg(point p1, point p2, point p3, point p4)  //平行线段之间的最短距离
    129 {
    130     return min(min(dis_p_to_seg(p1,line(p3,p4)),
    131            dis_p_to_seg(p2, line(p3, p4))),
    132            min(dis_p_to_seg(p3,line(p1, p2)),
    133            dis_p_to_seg(p4,line(p1, p2)))
    134         );
    135 }
    136 bool intbr(line l1,line l2) {            //    线段相交
    137     return
    138     max(l1.a.x,l1.b.x) >= min(l2.a.x,l2.b.x) &&
    139     max(l2.a.x,l2.b.x) >= min(l1.a.x,l1.b.x) &&
    140     max(l1.a.y,l1.b.y) >= min(l2.a.y,l2.b.y) &&
    141     max(l2.a.y,l2.b.y) >= min(l1.a.y,l1.b.y) &&
    142     cmp((l2.a-l1.a)^(l1.b-l1.a))*cmp((l2.b-l1.a)^(l1.b-l1.a)) <= 0 &&
    143     cmp((l1.a-l2.a)^(l2.b-l2.a))*cmp((l1.b-l2.a)^(l2.b-l2.a)) <= 0;
    144 }
    145 point line_inter(point A,point B,point C,point D){ //直线相交交点
    146         point ans;
    147         double a1=A.y-B.y;
    148         double b1=B.x-A.x;
    149         double c1=A.x*B.y-B.x*A.y;
    150 
    151         double a2=C.y-D.y;
    152         double b2=D.x-C.x;
    153         double c2=C.x*D.y-D.x*C.y;
    154 
    155         ans.x=(b1*c2-b2*c1)/(a1*b2-a2*b1);
    156         ans.y=(a2*c1-a1*c2)/(a1*b2-a2*b1);
    157         return ans;
    158 }
    159 
    160 int n;
    161 point ttmp;
    162 point pt1[1001000],pt2[1001000];
    163 bool cmpx(point xx,point yy){
    164     if(cmp(xx.y-yy.y)==0) return xx.x<yy.x;
    165     return xx.y<yy.y;
    166 }
    167 bool cmpd(point xx, point yy){
    168     double db=(xx-ttmp)^(yy-ttmp);
    169     if(cmp(db)==0) return dist(xx,ttmp)<dist(yy,ttmp);
    170     if(cmp(db)>0) return 1;
    171     else return 0;
    172 }
    173 point grp1[1001000],grp2[1001000];
    174 int Graham(point* grp,point *pt,int n){             //凸包
    175     int top=1;
    176     sort(pt,pt+n,cmpx);ttmp=pt[0];
    177     sort(pt+1,pt+n,cmpd);
    178     grp[0]=pt[0];
    179     grp[1]=pt[1];
    180     for(int i=2;i<n;i++){
    181         while(top>0){
    182             double db=(pt[i]-grp[top])^(grp[top]-grp[top-1]);
    183             if(cmp(db)>=0) top--;
    184             else break;
    185         }
    186         grp[++top]=pt[i];
    187     }
    188     return top+1;
    189 }
    190 double rotating_calipers(point* grp ,int len){ //旋转卡壳求凸包直径
    191     int i=0,j=1;
    192     double ans=0;
    193     while(i<len){
    194         while(area(grp[i],grp[i+1],grp[(j+1)%len])>
    195               area(grp[i],grp[i+1],grp[j])) j=(j+1)%len;
    196         ans=max(ans,max(dist(grp[i],grp[j]),dist(grp[i+1],grp[j])));
    197         i++;
    198     }
    199    return ans;
    200 }
    201 double rotating_calipers2(point* grp1,int len1,point* grp2,int len2){             //旋转卡壳 求两个凸包的最远距离
    202     int p=0,q=0;
    203     for(int i=0;i<len1;i++) if(grp1[i].y<grp1[p].y) p=i;
    204     for(int i=0;i<len2;i++) if(grp2[i].y>grp2[q].y) q=i;
    205     double ans=1e99,tmp;
    206     grp1[len1]=grp1[0];//避免取模
    207     grp2[len2]=grp2[0];//避免取模
    208     for(int i=0;i<len1;i++){
    209         while(tmp=cmp(area(grp1[p],grp1[p+1],grp2[q+1])-
    210               area(grp1[p],grp1[p+1],grp2[q]))>0)   q=(q+1)%len2;
    211         if(tmp==0) ans=min(ans,dis_pall_seg(grp1[p],grp1[p+1],grp2[q],grp2[q+1]));
    212         else ans=min(ans,dis_p_to_seg(grp2[q],line(grp1[p],grp1[p+1])));
    213         p=(p+1)%len1;
    214     }
    215 
    216     return ans;
    217 }
    218 double rotating_calipers3(point* grp ,int len){             //旋转卡壳求凸包宽度
    219     int p=0,q=0;
    220     int tmp;
    221     for(int i=0;i<len;i++) if(grp[i].y<grp[p].y) p=i;
    222     for(int j=0;j<len;j++) if(grp[j].y>grp[q].y) q=j;
    223     double ans=1e30;
    224     for(int i=0;i<len;i++){
    225         while(tmp=cmp(area(grp[p],grp[p+1],grp[(q+1)%len])-
    226               area(grp[p],grp[p+1],grp[q]))>0) q=(q+1)%len;
    227         ans=min(ans,dis_p_to_line(grp[q],line(grp[p],grp[(p+1)%len])));
    228         p=(p+1)%len;
    229     }
    230     return ans;
    231 }
    232 double rotating_calipers4(point* grp,int len){
    233     double ans;
    234     int xmin=0,xmax=0,ymin=0,ymax=0;
    235     for(int i=0;i<len;i++) if(cmp(grp[xmin].x-grp[i].x)>0) xmin=i;
    236     for(int i=0;i<len;i++) if(cmp(grp[xmax].x-grp[i].x)<0) xmax=i;
    237     for(int i=0;i<len;i++) if(cmp(grp[ymin].y-grp[i].y)>0) ymin=i;
    238     for(int i=0;i<len;i++) if(cmp(grp[ymax].y-grp[i].y)<0) ymax=i;
    239     ans=(grp[ymax].y-grp[ymin].y)*(grp[xmax].x-grp[xmin].x);
    240     grp[len]=grp[0];
    241     for(int i=0;i<len;i++){
    242         while(cmp(area(grp[ymin],grp[ymin+1],grp[ymax+1])-
    243                   area(grp[ymin],grp[ymin+1],grp[ymax]))>=0) ymax=(ymax+1)%len;
    244         while(cmp(dot(grp[xmax+1],grp[ymin],grp[ymin+1])-
    245                   dot(grp[xmax],grp[ymin],grp[ymin+1]))>=0) xmax=(xmax+1)%len;
    246         if(i==0) xmin=xmax;
    247         while(cmp(dot(grp[xmin+1],grp[ymin+1],grp[ymin])-
    248                   dot(grp[xmin],grp[ymin+1],grp[ymin]))>=0) xmin=(xmin+1)%len;
    249         double L1=dis_p_to_line(grp[ymax],line(grp[ymin],grp[ymin+1]));
    250         point a=P_chuizhi_line(grp[xmin],grp[ymin],grp[ymin+1]);
    251         double L2=dis_p_to_line(grp[xmax],line(grp[xmin],a));
    252         if(ans>L1*L2){
    253             ans=L1*L2;
    254 
    255         }
    256         ymin=(ymin+1)%len;
    257     }
    258     return ans;
    259 }
    260 struct node{
    261     double angle;
    262 }fuck[1000];
    263 bool nodecmp(node a,node b){
    264     return a.angle<b.angle;
    265 }
    266 int main(){
    267     #ifndef ONLINE_JUDGE
    268     freopen("input.txt","r",stdin);
    269     #endif // ONLINE_JUDGE
    270     int t;cin>>t;
    271     while(t--){
    272         scanf("%d",&n);
    273         for(int i=0;i<n;i++) pt1[i].input();
    274         long long ans=1ll*n*(n-1)*(n-2)*(n-3)/24;
    275         for(int i=0;i<n;i++){
    276             int cnt=0;
    277             for(int j=0;j<n;j++) if(i!=j){
    278                 fuck[cnt++].angle=(pt1[j]-pt1[i]).angle()+pi;
    279             }
    280             sort(fuck,fuck+cnt,nodecmp);
    281             for(int j=cnt;j<2*cnt;j++) fuck[j].angle=fuck[j-cnt].angle+2*pi;
    282             int st=1;
    283             long long tmp=0;
    284             for(int j=0;j<cnt;j++){
    285                 while(fuck[st].angle-fuck[j].angle<pi) st++;
    286                 if(st-j-1<2) continue;
    287                 tmp+=(st-j-1)*(st-j-2)/2;
    288             }
    289             ans-=(1ll*(n-1)*(n-2)*(n-3)/6-tmp);
    290         }
    291         printf("%lld
    ",ans);
    292     }
    293 }
  • 相关阅读:
    Iterator迭代器与增强for循环
    java中的集合
    基本类型包装类、System类
    java之Calendar类
    java二维数组
    java学习之字符串缓冲区
    java学习之内部类、包与代码块
    DataGridView列增加单选按钮、输入框
    DataGridView加上默认的序号
    数据结构简介
  • 原文地址:https://www.cnblogs.com/ainixu1314/p/4721427.html
Copyright © 2011-2022 走看看