Desert
题意:二维平面给出n个点,在这些点建立广播站,广播的角度为90度,每个点最多只能建一个且有一个代价,建立的广播站要把其他所有点覆盖,问建立三个最小代价为多少,如果无解输出impossible。
解法:很明显这个点一定在凸包上,做一遍凸包,再用点成判断角度是否小于等于90度,最后排一次徐就好了
//队友
#include<cstdio>
#include<cmath>
#include<algorithm>
using namespace std;
#define repi(i,A,B) for(int i=A;i<=B;i++)
#define rep(i,A,B) for(i=A;i<=B;i++)
struct node
{
double x,y;
int cost,num;
double ang;
node(){}
node(double p,double q,int r,int s)
{
x=p; y=q; cost=r; num=s;
ang=atan2(q,p);
}
bool operator<(node p)const
{
if(x==p.x) return y<p.y;
return x<p.x;
}
};
const int Len=20010;
node pos[Len];
int n;
int s[Len];
node c[Len];
node d[Len];
int a[Len];
int m;
double pi;
double cross(node a,node b)
{
return a.x*b.y-b.x*a.y;
}
node operator-(const node &a,const node &b)
{
return (node){a.x-b.x,a.y-b.y,0,0};
}
int work()
{
m=0;
repi(i,1,n)
{
while(m>1 && cross(pos[s[m-1]]-pos[s[m-2]],pos[i]-pos[s[m-2]])<=0) m--;
s[m++]=i;
}
int k=m;
for(int i=n-1;i>=1;i--)
{
while(m>k && cross(pos[s[m-1]]-pos[s[m-2]],pos[i]-pos[s[m-2]])<=0) m--;
s[m++]=i;
}
if(n>1) m--;
repi(i,0,m-1)
{
c[i]=pos[s[i]];
// printf("%lf %lf %d\n",c[i].x,c[i].y,c[i].num);
}
}
double calc(node a)
{
return atan2(a.y,a.x);
}
bool cmp(node p,node q)
{
return p.cost<q.cost;
}
void output()
{
a[1]=d[1].num;
a[2]=d[2].num;
a[3]=d[3].num;
sort(a+1,a+4);
printf("%d %d %d\n",a[1],a[2],a[3]);
}
double dot(node a,node b)
{
return a.x*b.x+a.y*b.y;
}
void check()
{
double d1,d2,del;
int t=0;
repi(i,0,m-1)
{
node p=c[(i+1)%m]-c[i];
node q=c[(i-1+m)%m]-c[i];
if(dot(p,q)>=0)
d[++t]=c[i];
}
sort(d+1,d+t+1,cmp);
if(t<3)
{
printf("Impossible\n");
}
else
{
output();
}
}
int main()
{
double x,y;
int z;
pi=acos(-1.0);
while(scanf("%d",&n)!=EOF && n)
{
repi(i,1,n)
{
scanf("%lf%lf%d",&x,&y,&z);
pos[i]=(node){x,y,z,i};
// printf("%lf %lf %d\n",pos[i].x,pos[i].y,pos[i].num);
}
//repi(i,1,n)
// printf("%lf %lf %d %d %lf\n",pos[i].x,pos[i].y,pos[i].cost,pos[i].num,pos[i].ang);
sort(pos+1,pos+n+1);
work();
//repi(i,0,m-1)
// printf("%d\n",c[i].num);
check();
}
return 0;
}