把这个题专门写出来是因为我比赛时没做,并且学会了新的姿势。做法是枚举每个点i,以点i为中心,对其余点进行极角排序。注意atan2(double,double)这个函数的用法。为了使得点i在凸包上,极角排序后必须存在相邻点的极角差大于等于Pi(中间如果出现了点,需要删去)。因为atan的值域在-Pi和Pi之间,我们需要处理越过y轴负方向的情况方法是将atan小于0的值加上2*Pi。
下面的代码是参考cgy4ever写的。没有优化跑得比较慢。。
#include <bits/stdc++.h>
using namespace std;
#define ll long long
const double eps = 1e-8;
struct Point{
ll x,y;
Point(ll x,ll y):x(x),y(y){
}
Point(){
}
}pts[3010];
double ang[6010];
struct Vector{
ll x,y;
Vector(ll x,ll y):x(x),y(y){
}
Vector(){
}
Vector(Point A,Point B){
x=B.x-A.x;
y=B.y-A.y;
}
};
ll Cross(Vector A,Vector B){
return A.x*B.y - A.y*B.x;
}
int main(){
freopen("C-large-practice.in","r",stdin);
freopen("C-large-practice.out","w",stdout);
int t;
cin>>t;
int cas=0;
while(t--){
cas++;
int n;
cin>>n;
for(int i=1;i<=n;i++){
cin>>pts[i].x>>pts[i].y;
}
printf("Case #%d:\n",cas);
for(int i=1;i<=n;i++){
int ans=max(0,n-3);
int pos=0;
for(int j=1;j<=n;j++){
if(i==j)continue;
double d = atan2( pts[j].y-pts[i].y , pts[j].x-pts[i].x );
ang[pos++]=d;
ang[pos++]=d+2*M_PI;
}
sort(ang,ang+pos);
bool flag=1;
for(int j=0;j<n-1;j++){
int k=j+1;
while(ang[k]-ang[j]<M_PI-eps&&k<pos-1){
k++;
}
if(ang[k]-ang[j]>M_PI-eps){
ans=min(ans,k-j-1);
flag=0;
}
}
if(flag)ans=0;
cout<<ans<<endl;
}
}
return 0;
}