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\n",ans);
292     }
293 }
时间: 2024-11-20 06:47:38

hdu 3629 Convex的相关文章

hdu 3629 Convex(计数问题)

题目链接:hdu 3269 Convex 题目大意:给出n个点,问任选四个点可以组成多少个凸四边形. 解题思路:和uav11529的做法是一样的,只不过求的东西不一样. #include <cstdio> #include <cstring> #include <cmath> #include <algorithm> #include <iostream> using namespace std; typedef long long ll; co

hdu 5979 Convex

Convex Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/65536 K (Java/Others)Total Submission(s): 670    Accepted Submission(s): 438 Problem Description We have a special convex that all points have the same distance to origin point.As y

【转】[专题学习][计算几何]

原文地址:http://www.cnblogs.com/ch3656468/archive/2011/03/02/1969303.html 基本的叉积.点积和凸包等东西就不多说什么了,网上一搜一大堆,切一些题目基本熟悉了就差不多了. 一些基本的题目可以自己搜索,比如这个blog:http://blog.sina.com.cn/s/blog_49c5866c0100f3om.html 接下来,研究了半平面交,思想方法看07年朱泽园的国家队论文,模板代码参考自我校大牛韬哥: http://www.o

UVA 11529 - Strange Tax Calculation(计数问题)

题目链接:11529 - Strange Tax Calculation 题意:平面上n个建筑物,3个建筑物可以组成一个三角形,计算平均每个三角形内有多少个点 思路:问题等价于,求凹四边形的占所有四边形的比例,用O(n^2)的算法,跟 HDU 3629 Convex 这题是一个道理 代码: #include <stdio.h> #include <string.h> #include <math.h> #include <algorithm> using n

UVA - 11529 Strange Tax Calculation

The people living in large citieshave to pay more tax than people living in rural areas. That is because incities people have many facilities, which rural people don't have. Also peoplein large and famous cities tend to pay more tax than people livin

Hdu 3662 3D Convex Hull(三维凸包)

题目地址:http://acm.hdu.edu.cn/showproblem.php?pid=3662 思路:三维凸包模板. #include<cstdio> #include<vector> #include<cstring> #include<iostream> #include<algorithm> #define PR 1e-8 #define N 510 using namespace std; struct TPoint { doub

hdu 6219 Empty Convex Polygons

- -先mark了 http://blog.csdn.net/nyroro/article/details/45268767 https://vjudge.net/solution/1919422 #include <stdio.h> #include <algorithm> #include <string.h> using namespace std; #define maxn 110 struct point{ int x,y; point(){} point(i

HDU 6617 Enveloping Convex(凸包+半平面交+二分)

首先对于这m个点维护出一个凸包M,那么问题就变成了判断凸包P进行放大缩小能不能包含凸包M.(凸包P可以进行中心对称变换再进行放大缩小,见题意) 如何判断合适的相似比呢,我们可以用二分去放大缩小凸包P的坐标,得到最小的相似比. 接下来就是如何判断是否包含.我们需要对凸包P上的每一条向量,在凸包M上找到这么一个点,使得这个点左侧的所有凸包M上的点都在向量的左侧,那么我们可以直接同时逆时针枚举,用一个变量维护凸包M上的点,因为是同逆时针,凸包M上的点至少有一个只会被遍历一次,那么复杂度可以证明为On,

hdu 2108 Shape of HDU (数学)

Shape of HDU Time Limit: 3000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)Total Submission(s): 5059    Accepted Submission(s): 2294 Problem Description 话说上回讲到海东集团推选老总的事情,最终的结果是XHD以微弱优势当选,从此以后,"徐队"的称呼逐渐被"徐总"所取代,海东集