利用分式的性质可以很容易证明要求的是个三角形,这很简单。对于求三角形内的雷的个数,只需求出每条边上方有多少个雷,作一点运算即可。如
A,B,C(B是X轴坐标在中间的点),则AC(其上方的雷的个数)-AB-BC即可。
1 #include <iostream> 2 #include <cstdio> 3 #include <cstring> 4 #include <cmath> 5 using namespace std; 6 7 struct node{ 8 int x,y; 9 }; 10 node point[250],mine[550]; 11 int cpoint[250][250]; 12 13 void exchange(int &i,int &j){ 14 int tmp=i; 15 i=j; 16 j=tmp; 17 } 18 19 int count_point(int i,int j,int cm){ 20 int cp=0; 21 if(point[i].x>point[j].x) 22 exchange(i,j); 23 for(int k=0;k<cm;k++){ 24 if(mine[k].x>=point[i].x&&mine[k].x<point[j].x){\必须是开区间,否则会有重复计算,对于中间的一点。。 25 if((point[i].x-mine[k].x)*(point[j].y-mine[k].y)-(point[j].x-mine[k].x)*(point[i].y-mine[k].y)>0) 26 cp++; 27 } 28 } 29 return cp; 30 } 31 32 int main(){ 33 int T,n,m,kase=0; 34 scanf("%d",&T); 35 while(T--){ 36 double ans=1e15; 37 scanf("%d%d",&n,&m); 38 for(int i=0;i<n;i++){ 39 scanf("%d%d",&point[i].x,&point[i].y); 40 } 41 for(int i=0;i<m;i++){ 42 scanf("%d%d",&mine[i].x,&mine[i].y); 43 } 44 memset(cpoint,0,sizeof(cpoint)); 45 for(int i=0;i<n;i++){ 46 for(int j=i+1;j<n;j++) 47 cpoint[i][j]=count_point(i,j,m); 48 } 49 int i,j,k; 50 for(int ii=0;ii<n;ii++){ 51 for(int jj=ii+1;jj<n;jj++){ 52 for(int kk=jj+1;kk<n;kk++){ 53 i=ii; j=jj;k=kk; 54 if(point[i].x>=min(point[j].x,point[k].x)&&point[i].x<=max(point[j].x,point[k].x)) 55 exchange(i,i); 56 else if(point[j].x>=min(point[i].x,point[k].x)&&point[j].x<=max(point[i].x,point[k].x)) 57 exchange(i,j); 58 else if(point[k].x>=min(point[i].x,point[j].x)&&point[k].x<=max(point[i].x,point[j].x)) 59 exchange(i,k); 60 double area=fabs(((point[j].x-point[i].x)*(point[k].y-point[i].y)-(point[k].x-point[i].x)*(point[j].y-point[i].y))/2.0); 61 double cp=abs((cpoint[i][j]+cpoint[j][i])+(cpoint[i][k]+cpoint[k][i])-(cpoint[j][k]+cpoint[k][j])); 62 ans=min(ans,area/cp); 63 } 64 } 65 } 66 printf("Case #%d: ",++kase); 67 if(ans==1e15) 68 printf("-1 "); 69 else printf("%.6lf ",ans); 70 } 71 return 0; 72 }