HDU_5784_HowManyTriangles(极角排序&&尺取法)

How Many Triangles

Time Limit: 10000/5000 MS (Java/Others)    Memory Limit: 65536/65536 K (Java/Others)
Total Submission(s): 559    Accepted Submission(s): 179


Problem Description
Alice has n points in two-dimensional plane. She wants to know how many different acute triangles they can form. Two triangles are considered different if they differ in at least one point.
 

Input
The input contains multiple test cases.
For each test case, begin with an integer n,
next n lines each contains two integers xi and yi.
3n2000
0xi,yi1e9
Any two points will not coincide.
 

Output
For each test case output a line contains an integer.
 

Sample Input
 
   
3 1 1 2 2 2 3 3 1 1 2 3 3 2 4 1 1 3 1 4 1 2 3
 

Sample Output
 
   
0 1 2
 

Author
ZSTU
 

Source
2016 Multi-University Training Contest 5
 

Recommend
wange2014

题意

给出平面上一些点

然后问平面上有多少个锐角三角形


解题思路

如果枚举3个点判断是否都是锐角,方案可行吗?

这样可以跑出答案但是O(N^3)肯定是不行的

不过标程里也写了,这个用来对拍还是蛮不错的


那么思路需要转化下,其实数三角形不如数角方便。

但是直接数所有的锐角数量是不对的

众所周知,直角三角形和钝角三角形也有两个锐角

因此,我们应当数出所有的锐角,钝角和直角。

然后(锐角数量-直角钝角数量*2)/3就可以得到锐角三角形的数量了


怎么数角呢?首先枚举中心(顶点)

然后以顶点为中心极角排序

之后把点再复制一遍,这样方便处理

之后利用尺取法,逐渐的推起始边和末尾边

这里注意要把起始边重边跳掉j

然后判断最后一个能形成锐角的位置k和最后一个能形成钝角的位置l

减下就知道目前状态下能得到的各种角的数目了


题目很仁慈点坐标都是整数

所以这个题目并不涉及精度问题

那不涉及精度问题其实也是问题

这种情形下再用tan2进行极角排序就不如直接用叉积来的方便了

#include 
#include 
#include 
#include 
using namespace std;

typedef long long LL;
const int M=2005;

struct Point
{
    int x,y;
    Point(int _x = 0,int _y = 0) : x(_x),y(_y) {}
    Point operator+(const Point &a)const
    {
        return Point(x+a.x,y+a.y);
    }
    Point operator-(const Point &a)const
    {
        return Point(x-a.x,y-a.y);
    }
    Point operator=(const Point &a)
    {
        x=a.x;y=a.y;
        return *this;
    }
    void read()
    {
        scanf("%d%d",&x,&y);
    }
    void show()const
    {
        printf("%d %d\n",x,y);
    }
}p_or[M],pn[M*2];
LL det(const Point &a,const Point &b)
{
    return (LL)a.x*b.y-(LL)a.y*b.x;
}
LL dot(const Point &a,const Point &b)
{
    return a.x * 1ll * b.x + a.y * 1ll * b.y;
}

bool polar_cmp(const Point &a,const Point &b)
{
    if((LL)a.y*b.y<=0)
    {
        if(a.y>0||b.y>0) return a.y0;
}

int n;
LL ans;
LL naa,noa;//锐角数量,直角钝角数量
void cntaa(int core)//寻找以某点为中心的锐角,钝角直角数量
{
    //cout<<"core "<0)
            j++;
        k=max(j,k);
        while(k0&&dot(pn[i],pn[k])>0)
            k++;
        l=max(k,l);
        while(l0)
            l++;
        naa+=k-j;
        noa+=l-k;
        //cout<<"naa noa "<


你可能感兴趣的:(HDU,极角排序,尺取法)