HDU 3629 极角排序

题意:

给你n个点(4~700), 问你能够成多少个不同的凸四边形。

 

题解:

只要求所有凹四边形即可。

对于每个点,凹四边形的个数等于:C(n-1,3)-在这个点同一侧三点构成的三角形的个数。

对于凸多边形的一个顶点,其他顶点必然在穿过这个顶点的直线的同侧。

 

处理这个有一个好方法,我以前一直没发现。

算极角时,如果是负数(-pi ~ 0),就把它加上2 * pi,这样就把角度统一到了0~2pi。

另外,向这题顺次统计两个点的夹角时,由于会出现转了一圈的情况不好计算角度,所以在原来数组后面再顺次加上n-1一个点,角度同一加2pi

这个方法真的很好用~

 

View Code
 1 #include <iostream>

 2 #include <cstring>

 3 #include <cstdio>

 4 #include <cstdlib>

 5 #include <algorithm>

 6 #include <cmath>

 7 

 8 #define N 22222

 9 #define EPS 1e-8

10 

11 using namespace std;

12 

13 struct PO

14 {

15     double x,y;

16 }p[N];

17 

18 const double PI=acos(-1.0);

19 double ag[N];

20 int n;

21 

22 inline void read()

23 {

24     scanf("%d",&n);

25     for(int i=1;i<=n;i++) scanf("%lf%lf",&p[i].x,&p[i].y);

26 }

27 

28 inline int dc(double x)

29 {

30     if(x>EPS) return 1;

31     else if(x<-EPS) return -1;

32     return 0;

33 }

34 

35 inline long long c(long long a,long long b)

36 {

37     if(a<b) return 0;

38     long long res=1LL;

39     for(long long i=a;i>=a-b+1;i--) res*=i;

40     for(long long i=b;i>=1;i--) res/=i;

41     return res;

42 }

43 

44 inline void go()

45 {

46     long long ans=0;

47     for(int i=1;i<=n;i++)

48     {

49         for(int j=1;j<=n;j++)

50         {

51             if(i==j) continue;

52             double tmp=atan2(p[j].y-p[i].y,p[j].x-p[i].x);

53             if(dc(tmp)<0) tmp+=2*PI;

54             if(j<i) ag[j]=tmp;

55             else ag[j-1]=tmp;

56         }

57         sort(ag+1,ag+n);

58         for(int j=1;j<=n-1;j++) ag[j+n-1]=ag[j]+2*PI;

59         long long res=0; int p2=2;

60         for(int p1=1;p1<=n-1;p1++)

61         {

62             while(fabs(ag[p2]-ag[p1])-PI<0) p2++;

63             res+=c(p2-p1-1,2);

64         }

65         ans+=c(n-1,3)-res;

66     }

67     printf("%I64d\n",c(n,4)-ans);

68 }

69 

70 int main()

71 {

72     int cas; scanf("%d",&cas);

73     while(cas--) read(),go();

74     return 0;

75 }

 

 

你可能感兴趣的:(HDU)