P6341 [COCI2007-2008#2] PRAVOKUTNI 题解
看了一下别人都写的是
又
反过来,当
又
那要如何判断
所以解法流程:
- 枚举作为原点的点,平移其他点,并旋转到第一象限。
- 按照斜率排序,斜率相同的点都会连成一段。
- 统计四个象限斜率相同的点,相邻象限点数相乘累加答案
总的时间复杂度
补充: 排序时要判断
代码:
#include<iostream>
#include<cstdio>
#include<algorithm>
#define ll long long
using namespace std;
struct point
{
ll x,y;int k;//横纵坐标和象限
}p[1505];
int n,ans=0;
ll x[1505],y[1505];
void swap(int &a,int &b){a=a^b,b=a^b,a=a^b;}
void xz(int t)
{//我写了顺时针旋转,这样方便计算在第几象限,坐标关系可以手推出来
p[t].k++,swap(p[t].x,p[t].y),p[t].y=-p[t].y;
}
bool cmp(point a,point b)
{//比较斜率,为了避免误差把除法通分换乘法
return a.y*b.x<b.y*a.x;
}
int main()
{
scanf("%d",&n);
for(int i=1;i<=n;i++)scanf("%lld%lld",&x[i],&y[i]);
for(int i=1;i<=n;i++)
{
for(int j=1;j<=n;j++)
{
if(j!=i)
{
p[j].x=x[j]-x[i],p[j].y=y[j]-y[i],p[j].k=1;
while(p[j].x<=0||p[j].y<0)xz(j);//一直转到第一象限,可能在坐标轴上所以横坐标等于零也要转
}
else p[i]=p[1];//原点不能排序,因为不能除以零,会出问题
}
sort(p+2,p+1+n,cmp);
for(int j=2,k;j<=n;j=k)//从上次结束的地方开始
{
int s[4]={0};//统计四个象限
for(k=j;k<=n;s[p[k].k-1]++,k++)if(p[j].y*p[k].x!=p[k].y*p[j].x)break;//排序后相同的肯定时连续一段,不相同直接break
for(int i=0;i<=3;i++)ans+=s[i]*s[(i+1)%4];
}
}
printf("%d",ans);
return 0;
}