HDU5784How Many Triangles(几何+极角排序)

题意:

平面上n个点,问能组成多少个锐角三角形


题解的方法就比较好 
统计锐角的个数,设为  A ,钝角和直角的个数,设为  B  
每个锐角三角形有三个锐角,每个钝角和直角三角形均贡献两个锐角 
所以答案即为  A2B3  
然后题解在对每个点极角排序之后,采用 two pointers的方式来找上下界 
比二分好写多了,也很方便,时间复杂度  O(N2logN)

代码一:


#include<bits/stdc++.h>
using namespace std;
#define LL long long
#define N 2005
const double pi=acos(-1.0);
int n;
struct node
{
    double x, y;
}p[N];
double ang[N*2];
void solve()
{
    for(int i=1; i<=n; i++) cin>>p[i].x>>p[i].y;
    LL ans1=0, ans2=0;
    for(int i=1; i<=n; i++)
    {
        int cnt=0;
        for(int j=1; j<=n; j++)
        {
            if(i==j) continue;
            ang[++cnt]=atan2(p[i].y-p[j].y, p[i].x-p[j].x);
            if(ang[cnt]<0) ang[cnt]+=2*pi;
        }
        sort(ang+1, ang+cnt+1);
        for(int j=1; j<=cnt; j++) ang[j+cnt]=ang[j]+2*pi;
        LL l=1, r=1, len=1;
        for(int j=1; j<=cnt; j++)
        {
            while(r<2*cnt&&ang[r]-ang[j]<pi) r++;
            while(l<2*cnt&&ang[l]-ang[j]<0.5*pi) l++;
            while(len<2*cnt&&ang[j]==ang[len]) len++;
            ans1+=l-len;
            ans2+=r-l;
        }
    }
    printf("%I64d\n", (ans1-2*ans2)/3);
}
int main()
{
    while(cin>>n)
    {
        solve();
    }
    return 0;
}

代码二:

#include<bits/stdc++.h>
using namespace std;
#define LL long long
#define N 2005
const double pi=acos(-1.0);
const double eps=1e-12;
int n;
int sgn(double x)
{
    return x>eps?1:(x<-eps?(-1):0);
}
struct node
{
    double x, y;
    node operator -(const node&other)const
    {
        return {x-other.x, y-other.y};
    }
}p[N];
double ang[N*2];
int calc(double angle)
{
    int r=0, ret=0;
    for(int l=0; l<n-1; l++)
    {
        int eql=0;
        while(sgn(ang[l+eql]-ang[l])==0) eql++;
        l=l+eql-1;
        r=max(r, l+1);
        while(r-l+1<=n-1&&sgn(ang[r]-ang[l] - angle) < 0) r++;
        ret += (r-l-1)*eql;
    }
    return ret;
}
void solve()
{
    LL ans1=0, ans2=0;
    for(int i=0; i<n; i++) cin>>p[i].x>>p[i].y;
    for(int i=0; i<n; i++)
    {
        node tmp;
        for(int j=i+1; j<i+n; j++)
        {
            int id=j%n;
            tmp=p[id]-p[i];
            ang[j-i-1]=atan2(tmp.y, tmp.x);
        }
        sort(ang, ang+n-1);
        for(int j=0; j<n-1; j++) ang[j+n-1]=ang[j]+2*pi;
        int ret=calc(pi*0.5);
        ans1+=ret;
        ans2+=calc(pi)-ret;
    }
    printf("%I64d\n", (ans1-2*ans2)/3);
}
int main()
{
    while(cin>>n)
    {
        solve();
    }
    return 0;
}


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值