刚看到这道题时,第一感觉是双重循环,求出所有的交点的横坐标,然后判断是不是在所给范围内。
毫无疑问,结果肯定超时。但换个角度想一下,转化为zoj3129的japan那道题,即是求逆序对的个数。
接下来就和3129一样了。。。
#include<stdio.h>
#include<string.h>
#include<stdlib.h>
#include<math.h>
#include<float.h>
#define N 10005
struct node{
double first;
double second;
}f[N];
double s[N],t[N];
double a[N][4];
int i,j,k,m,n;
double l,r;
int ans;
int cmp( const void *a , const void *b )
{
struct node *c = (struct node *)a;
struct node *d = (struct node *)b;
if (fabs(c->first - d->first)<0.0000001) // 即是不相等
return c->second > d->second ? 1 : -1 ;
return c->first > d->first ? 1 : -1 ;
}
void merge(int x,int z,int y)
{
int n1,n2;
n1=z-x+1; n2=y-z;
i=0;j=0;
for (k=x;k<=z;k++)
s[i++]=f[k].second;
s[n1]=DBL_MAX;
for (k=z+1;k<=y;k++)
t[j++]=f[k].second;
t[n2]=DBL_MAX;
i=0; j=0;
for(k=x;k<=y;k++){
if (s[i]>t[j]){
ans+=(n1-i);
f[k].second=t[j++];
}
else
f[k].second=s[i++];
}
}
void merge_sort(int x, int y)
{
int z;
if(x<y){
z=(x+y)/2;
merge_sort(x, z);
merge_sort(z+1, y);
merge(x,z,y);
}
}
int main()
{
while(scanf("%d",&n)!=EOF)
{
for(i=0;i<n;i++)
for (j=0;j<4;j++)
scanf("%lf", &a[i][j]);
scanf("%lf%lf", &l,&r);
for(i=0;i<n;i++){
f[i].first=((l-a[i][0])*(a[i][3]-a[i][1])/(a[i][2]-a[i][0]))+a[i][1]; // 平行于y轴的直线x=l与两点确定的直线的交点的纵坐标
f[i].second=((r-a[i][0])*(a[i][3]-a[i][1])/(a[i][2]-a[i][0]))+a[i][1]; // 平行于y轴的直线x=l与两点确定的直线的交点的纵坐标
}
qsort(f,n,sizeof(f[0]),cmp);
ans=0;
merge_sort(0,n-1);
printf("%d\n",ans);
}
return 0;
}