http://acm.hdu.edu.cn/showproblem.php?pid=4197
题目说要飞最少的飞镖把所有气球穿破。
对于任意一个气球,要把它打破,扔的飞镖必然是在它的两条切线的上下界内。
然后排序,枚举起点定义方向进行贪心。
View Code
1 #include <iostream> 2 #include <stdio.h> 3 #include <string.h> 4 #include <math.h> 5 #include <algorithm> 6 #include <limits.h> 7 using namespace std; 8 #define PI 3.14159265358979 9 #define eps 1e-6 10 struct node{ 11 double l,r; 12 }w[1010]; 13 bool cmp(const node &a,const node &b){ 14 return a.l<b.l; 15 } 16 int zero(double x){ 17 return fabs(x)<eps; 18 } 19 int dd(double x,double y){ 20 return fabs(x-y)<eps; 21 } 22 int dy(double x,double y){ 23 return x>y+eps; 24 } 25 int xy(double x,double y){ 26 return x+eps<y; 27 } 28 int dyd(double x,double y){ 29 return x+eps>y; 30 } 31 int xyd(double x,double y){ 32 return y+eps>x; 33 } 34 int live(double l,double r,double x){ 35 if(xyd(l,r)&&xyd(l,x)&&xyd(x,r)) return 1; 36 if(dy(l,r)&&(xyd(l,x)||xyd(x,r))) return 1; 37 return 0; 38 } 39 int main(){ 40 int T,n,a,b,c; 41 scanf("%d",&T); 42 while(T--){ 43 scanf("%d",&n); 44 for(int i=0;i<n;++i){ 45 scanf("%d%d%d",&a,&b,&c); 46 double dis=double(a*a+b*b); 47 double s; 48 double tr=asin(double(c)/sqrt(dis)); 49 if(!a){ 50 if(b>=0) s=PI/2; 51 else s=-PI/2; 52 } 53 else{ 54 s=atan(double(b)/a); 55 if(a<0){ 56 if(b<0) s-=PI; 57 else s+=PI; 58 } 59 } 60 w[i].l=s-tr; 61 w[i].r=s+tr; 62 if(w[i].l<-PI) w[i].l+=2*PI; 63 if(w[i].r>PI) w[i].r-=2*PI; 64 } 65 sort(w,w+n,cmp); 66 int ans=n; 67 for(int i=0;i<n;++i){ 68 double L,R; 69 int num=1; 70 L=w[i].l,R=w[i].r; 71 for(int j=1;j<n;++j){ 72 int v=(i+j)%n; 73 if(!live(L,R,w[v].l)){ 74 L=w[v].l; 75 R=w[v].r; 76 num++; 77 } 78 else{ 79 L=w[v].l; 80 if(live(L,R,w[v].r)) R=w[v].r; 81 } 82 } 83 ans=min(ans,num); 84 } 85 printf("%d\n",ans); 86 } 87 return 0; 88 }