HDU 5784 How Many Triangles(极角排序)
2016-08-21 15:42
351 查看
题意很简单,平面上给你n个点,求锐角三角形的个数,点没有重复
首先就是随便选三个点C(n,3),可能构成锐角,直角,钝角,并且直角钝角都不会重复计算
所以锐角的个数就是C(n,3)−直角−钝角−三点共线
这里用点乘和叉乘来求解直角钝角还有三点共线的问题
首先枚举点,然后对其他点和它构成的向量,做极角排序
然后对一个向量v,找它左边的向量w,如果cross(w,v)<0,表示w在v的左边
然后如果dot(v,w)≤0,表示他们是直角或者钝角
三点共线在排序完之后,看cross(v,w)==0,dot(v,w)>0
细节就是这题每个向量最好要存两遍,求解直角钝角的时候不好写,要用左边的向量个数−左边锐角个数=左边直角钝角个数,然后再减去
直接找一个向量左边直角钝角的范围,不好找
代码:
首先就是随便选三个点C(n,3),可能构成锐角,直角,钝角,并且直角钝角都不会重复计算
所以锐角的个数就是C(n,3)−直角−钝角−三点共线
这里用点乘和叉乘来求解直角钝角还有三点共线的问题
首先枚举点,然后对其他点和它构成的向量,做极角排序
然后对一个向量v,找它左边的向量w,如果cross(w,v)<0,表示w在v的左边
然后如果dot(v,w)≤0,表示他们是直角或者钝角
三点共线在排序完之后,看cross(v,w)==0,dot(v,w)>0
细节就是这题每个向量最好要存两遍,求解直角钝角的时候不好写,要用左边的向量个数−左边锐角个数=左边直角钝角个数,然后再减去
直接找一个向量左边直角钝角的范围,不好找
代码:
#include <map> #include <set> #include <ctime> #include <stack> #include <queue> #include <cmath> #include <string> #include <vector> #include <cstdio> #include <cctype> #include <cstring> #include <sstream> #include <cstdlib> #include <iostream> #include <algorithm> #pragma comment(linker,"/STACK:102400000,102400000") using namespace std; #define MAX 1000005 #define MAXN 1000005 #define maxnode 205 #define sigma_size 26 #define lson l,m,rt<<1 #define rson m+1,r,rt<<1|1 #define lrt rt<<1 #define rrt rt<<1|1 #define middle int m=(r+l)>>1 #define LL long long #define ull unsigned long long #define mem(x,v) memset(x,v,sizeof(x)) #define lowbit(x) (x&-x) #define pii pair<int,int> #define bits(a) __builtin_popcount(a) #define mk make_pair #define limit 10000 //const int prime = 999983; const int INF = 0x3f3f3f3f; const LL INFF = 0x3f3f; const double pi = acos(-1.0); const double inf = 1e18; const double eps = 1e-4; const LL mod = 772002; const ull mx = 133333331; /*****************************************************/ inline void RI(int &x) { char c; while((c=getchar())<'0' || c>'9'); x=c-'0'; while((c=getchar())>='0' && c<='9') x=(x<<3)+(x<<1)+c-'0'; } /*****************************************************/ struct point{ LL x,y; point(LL x=0,LL y=0):x(x),y(y){} point operator - (const point &t)const{ return point(x-t.x,y-t.y); } LL operator * (const point &t)const{ /// 叉积 : 有向面积 return x*t.y-y*t.x; } LL operator ^ (const point &t)const{ /// 点积 : 有向长度 return x*t.x+y*t.y; } bool operator < (const point &t)const{ /// 极角排序 bool up[2]={0,0}; if(y>0 || (y==0 && x>0)) up[0]=1; if(t.y>0 || (t.y==0 && t.x>0)) up[1]=1; if(up[0]^up[1]) return up[0]; return (*this)*t ? (*this)*t>0 : ((*this)^(*this))<(t^t); } }p[MAX],v[MAX*2]; int main(){ //freopen("1002.in","r",stdin); //freopen("froggy.out","w",stdout); int n; while(cin>>n){ for(int i=1;i<=n;i++) scanf("%I64d%I64d",&p[i].x,&p[i].y); LL ans=(LL)n*(n-1)*(n-2)/6; LL tmp=0; for(int i=1;i<=n;i++){ int tot=0; for(int j=1;j<=n;j++){ if(i==j) continue; v[tot++]=p[j]-p[i]; } sort(v,v+tot); for(int j=0;j<tot;j++) v[j+tot]=v[j]; int num=0; for(int j=1;j<tot;j++){ if(v[j]*v[j-1]==0&&(v[j]^v[j-1])>0) num++;//三点共线且同向,最后要去掉 else num=0; tmp+=num; } int p1=0,p2=0; for(int j=0;j<tot;j++){ while(p1<=j||(p1<j+tot&&v[p1]*v[j]<0&&(v[p1]^v[j])>0)) p1++;//左边并且是锐角 while(p2<=j||(p2<j+tot&&v[p2]*v[j]<0)) p2++;//左边,锐角+钝角+直角 ans-=p2-p1; } } cout<<ans-tmp/2<<endl; } return 0; }
相关文章推荐
- hdu 5784 How Many Triangles 极角排序计算锐角直角钝角
- hdu-5784 How Many Triangles(计算几何+极角排序)
- [HDU 5784] How Many Triangles (几何+极角排序)
- HDU 5784 How Many Triangles 极角排序
- HDU 5784 How Many Triangles
- HDU 5784- How Many Triangles-计算几何-two-pointer-数锐角三角形个数
- HDU 5784 How Many Triangles
- Hdu 5784 How Many Triangles(极角排序+尺取法)
- HDU 5784 How Many Triangles(计算几何)
- HDU 5784 How Many Triangles
- HDU_5784_HowManyTriangles(极角排序&&尺取法)
- HDU 5784 How Many Triangles
- hdu 5784 How Many Triangles 计算几何,平面有多少个锐角三角形
- 【HDU5784】How Many Triangles(极角排序 + two-pointer)
- hdu 2760 how many shortest path
- hdu 2138 How many prime numbers(求素数)
- hdu 1130 How Many Trees?
- hdu 1948 How many ways
- soj 3137 Simple Computing 容斥原理 hdu 1796 How many integers can you find
- hdu How many prime numbers