hdu 3629组合几何,逆向思维降低复杂度
2014-04-19 13:10
190 查看
题目意思:
t个案例,每个案例n个整数点,求由n个点中任选四个组成凸四边形的个数。
http://acm.hdu.edu.cn/showproblem.php?pid=3629
分析:
注意fabs和atan2的参数问题,最好都使用double
暴力的话C(700,4)必然超时,发现,任何一个凹包必然是其中一点在其它3点构成的三角形内。
先求出凹边形的数目在用总数C (n,4)减去凹边形数就是答案。
依次枚举每个点i,看看其它点能够成多少个包括点i的三角形,就是以这个点为中心的凹包的个数。
找三角形也要一定的技巧,也是通过逆向思维:找出有多少个三角形不包括点i,然后用总三角形个数C(n– 1, 3) –这个个数就是就是以这个点为中心的凹包的个数。
注意到,如果3个点不能圈住中心点,则必然是存在一条通过中心点的直线,使得这三个点都在直线的同侧。利用这个形式,我们用如下方法寻找三角形:
1:以中心点为中心,对剩余n-1个点极角排序。
2:依次处理排序后的n-1个点,对于每一个点i,依次往后扫描,找到第一个点j,是j和i的夹角大于180度。
3:那么点i +1到点j – 1的所有点都可以和点i构成不包括中心点的三角形。个数是
C(j – i – 1,2)
代码:
t个案例,每个案例n个整数点,求由n个点中任选四个组成凸四边形的个数。
http://acm.hdu.edu.cn/showproblem.php?pid=3629
分析:
注意fabs和atan2的参数问题,最好都使用double
暴力的话C(700,4)必然超时,发现,任何一个凹包必然是其中一点在其它3点构成的三角形内。
先求出凹边形的数目在用总数C (n,4)减去凹边形数就是答案。
依次枚举每个点i,看看其它点能够成多少个包括点i的三角形,就是以这个点为中心的凹包的个数。
找三角形也要一定的技巧,也是通过逆向思维:找出有多少个三角形不包括点i,然后用总三角形个数C(n– 1, 3) –这个个数就是就是以这个点为中心的凹包的个数。
注意到,如果3个点不能圈住中心点,则必然是存在一条通过中心点的直线,使得这三个点都在直线的同侧。利用这个形式,我们用如下方法寻找三角形:
1:以中心点为中心,对剩余n-1个点极角排序。
2:依次处理排序后的n-1个点,对于每一个点i,依次往后扫描,找到第一个点j,是j和i的夹角大于180度。
3:那么点i +1到点j – 1的所有点都可以和点i构成不包括中心点的三角形。个数是
C(j – i – 1,2)
代码:
#include<iostream> #include<cstdio> #include<cmath> #include<algorithm> using namespace std; const double eps=1e-9; const double PI=acos(-1.0); long long C[707][707]; int n; int sig(double ag){ return (ag>eps)-(ag<-eps); } struct node{ double x,y; // int operator^(node a){ // return x*a.y-a.x*y; // } // bool operator<(node a){ // return (x*a.y-a.x*y)>0?true:false; // } }p[707]; void count(){ C[0][0]=C[1][0]=C[1][1]=1; for(int i=2;i<=700;i++){ C[i][0]=C[i][i]=1; for(int j=1;j<i;j++){ C[i][j]=C[i-1][j-1]+C[i-1][j]; } } } void read(){ scanf("%d",&n); for(int i=0;i<n;i++) scanf("%lf%lf",&p[i].x,&p[i].y); } void doit(){ long long ans=0; double angle[1414],temp; for(int i=0;i<n;i++){ for(int j=0;j<n;j++){ if(j==i)continue; temp=atan2(p[j].y-p[i].y,p[j].x-p[i].x ); if( sig(temp)<0)temp+=2*PI; if(j<i)angle[j]=temp; else angle[j-1]=temp; } sort(angle,angle+n-1); for(int j=0;j<n-1;j++){ angle[j+n-1]=angle[j]+2*PI; } long long res=0; int p2=1; for(int p1=0;p1<n-1;p1++){ while(fabs(angle[p2]-angle[p1])-PI<0)p2++; res+=C[p2-p1-1][2]; } ans+=(C[n-1][3]-res); } printf("%I64d\n",C [4]-ans); } int main() { int t; count(); scanf("%d",&t); while(t--){ read(); doit(); } return 0; }
相关文章推荐
- hdu 3629 Convex 计算几何
- hdu 3629 计算几何
- hdu 3629 计算几何
- HDU 5365 Run 计算几何 枚举 组合
- hdu 5185 动态规划 分析降低复杂度
- HDU 3629 Convex(10年天津,计算几何)
- hdu 3629 Convex 计算几何
- HDU 5581 Infinity Point Sets ACM/ICPC 2015 上海区域赛 I 计算几何+组合计数
- HDU-4569 Special equations (利用数学知识巧妙降低复杂度)
- HDU-3629-Convex-计算几何
- hdu 3629 计算几何
- !HDU 1506 Largest Rectangle in a Histogram-dp|单调队列-(dp降低时间复杂度)
- HDU 4503 湫湫系列故事——植树节(组合概率)
- 字符串移动(字符串为*号和26个字母的任意组合,把*号都移动到最左侧,把字母移到最右侧并保持相对顺序不变),要求时间和空间复杂度最小
- [hdu 2826] The troubles of lmy [简单计算几何 - 相似]
- 计算几何 之 hdu 1077 poj 1981 O(n^3)
- hdu 1411 校庆神秘建筑(计算几何)
- hdu 6036 NTT取模(板子)+组合数学
- HDU 3037 Saving Beans(组合数学+Lucas定理)
- hdu 4503 组合概率