不会写代码了。。扫描线忘记加 s = max(i,s) 了
然后没调出来。。。。。
退役两个多月了,感觉变成一张嘴了(((
思路还是很好想的,这也就一般通过扫描线吧。
我的思路:
考虑『 castle 』这个东西,
我们发现,如果是 三角形+中间一个点的话, 那么我们只要再随便加一个点就ok了
也就是『三角形包含一个点』*(n-4)
考虑计算 一个点被多少个三角形包含,
好难。 我们不如算 一个点 不被多少个三角形包含,简单。
对于一条扫描线,我们只要在它一侧选出两个点,那么这就是一个不包含 中心点的三角形了,
然后我们用C(n-1,3)减去不包含的三角形就能得到包含的三角形了。
然后用包含的三角形*(n-4)
测样例,咦,刚好都大了两倍,所以我们直接除以二提交
画个图,
发现确实是这样,不管四个点怎么放,中间的点都会被算进两个三角形里,所以贡献除以2
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
struct point{
ll x,y,id;
point operator +(const point & k1)const {return (point){k1.x+x,k1.y+y};}
point operator -(const point & k1)const {return (point){x-k1.x,y-k1.y};}
inline int getP()const {return y>0||(y==0&&x<0);}
};
inline ll cross(point k1,point k2){return k1.x*k2.y-k1.y*k2.x;}
inline ll dot(point k1,point k2){ return k1.x*k2.x+k1.y*k2.y;}
inline int compareangle(point k1,point k2){
return k1.getP()<k2.getP()||(k1.getP()==k2.getP()&&cross(k1,k2)>0);
}
ll n;
point p[2525];
ll slove(int id){//无三点共线
//找不包含 id 的三角形
vector<point> v;
for(int i=1;i<=n;i++)if(i!=id)v.push_back(p[i]-p[id]);
sort(v.begin(),v.end(),compareangle);
int m = v.size();
// for(auto x:v)cout<<x.x<<' '<<x.y<<endl;
for(int i=0;i<m;i++)v.push_back(v[i]);
ll res = 0;
int s=0;
for(int i=0;i<m;i++){
point _180 = {-v[i].x,-v[i].y};
s=max(i,s);
while (s<i+m-1&&(cross(v[s+1],_180)>0&&cross(v[s+1],v[i])<0))s++;
//s<180
int cnt = s-i;
res += 1ll*cnt*(cnt-1)/2;
}
ll sum = 1ll*(n-1)*(n-2)*(n-3)/6;
sum-=res;//被多少个三角形包含
return sum*(n-4);
}
int main(){
scanf("%lld",&n);
for(int i=1;i<=n;i++){
scanf("%lld%lld",&p[i].x,&p[i].y);
}
ll ans = 0;
for(int i=1;i<=n;i++){
// cout<<slove(i)<<endl;
ans+=slove(i);
}
cout<<ans/2<<endl;
}