利用叉积判断点和直线的位置关系,确定点在直线的左侧还是右侧
通过查找比较点与各个直线(隔板)之间的关系,确定点所在的区间
查找可以用一般方法,因为直线是有序的,但需要考虑0和n的特殊情况。
#include <iostream>
#include <cstdio>
#include <algorithm>
#include <cstdlib>
#include <cstring>
#define maxn 5000+10
typedef struct Point
{
int x,y;
}point;
typedef struct Line
{
point a,b;
}Line;
int ans[maxn];
int n;
Line line[maxn];
using namespace std;
int cross(point p0, point p1, point p2) //p0,p1是线段,p2是待判断的点
{
return (p2.x - p0.x)*(p1.y - p0.y)-(p1.x - p0.x)*(p2.y - p0.y);
}
void search(point toy) //搜索并利用叉积进行判断
{
if(cross(line[0].b,line[0].a,toy)<0)
ans[0]++;
else if(cross(line[n-1].b,line[n-1].a,toy)>0)
ans[n]++;
else
{
for(int i=0;i<n;i++)
if(cross(line[i].b,line[i].a,toy)>0&&cross(line[i+1].b,line[i+1].a,toy)<0)
ans[i+1]++;
}
}
int main()
{
point toy;
int m,x1,y1,x2,y2;
int u,l;
int xj,yj;
while(scanf("%d",&n) && n!=0)
{
scanf("%d%d%d%d%d",&m,&x1,&y1,&x2,&y2);
memset(ans,0,sizeof(ans));
for(int i=0;i<n;i++)
{
scanf("%d%d",&u,&l);
line[i].a.x=u;
line[i].a.y=y1;
line[i].b.x=l;
line[i].b.y=y2;
}
for(int i=0;i<m;i++)
{
scanf("%d%d",&xj,&yj);
point toy;
toy.x=xj;
toy.y=yj;
search(toy);
}
for(int i=0;i<=n;i++)
printf("%d: %d\n",i,ans[i]);
cout<<endl;
}
}
或者可以将矩形的两个高视为隔板,直接进行查找。
#include <iostream>
#include <cstdio>
#include <cstring>
#define maxn 5000+10
struct point
{
int x,y;
};
struct Line
{
point a,b;
};
int n;
int ans[maxn];
int cnt[maxn];
Line line[maxn];
using namespace std;
int cross(point p0,point p1,point p2)
{
return (p0.x-p2.x)*(p1.y-p2.y)-(p1.x-p2.x)*(p0.y-p2.y);
}
void search(point toy)
{
for(int i=0;i<=n;i++)
{
if(cross(toy,line[i].a,line[i].b)>0 && cross(toy,line[i+1].a,line[i+1].b)<0)
ans[i]++;
}
}
int main()
{
int m,x1,y1,x2,y2;
int u,l,xj,yj;
point toy;
while(scanf("%d",&n) && n!=0)
{
memset(ans,0,sizeof(ans));
memset(cnt,0,sizeof(cnt));
scanf("%d%d%d%d%d",&m,&x1,&y1,&x2,&y2);
line[0].a.x=x1; line[0].a.y=y1; //将矩形的两高视为隔板
line[0].b.x=x1;line[0].b.y=y2;
line[n+1].a.x=x2; line[n+1].a.y=y1;
line[n+1].b.x=x2; line[n+1].b.y=y2;
for(int i=1;i<=n;i++)
{
scanf("%d%d",&u,&l);
line[i].a.x=u;
line[i].a.y=y1;
line[i].b.x=l;
line[i].b.y=y2;
}
for(int i=0;i<m;i++)
{
scanf("%d%d",&xj,&yj);
toy.x=xj;
toy.y=yj;
search(toy);
}
for(int i=0;i<=n;i++)
printf("%d: %d\n",i,ans[i]);
cout<<endl;
}
}
复杂度低一些,二分查找
#include <iostream>
#include <cstdio>
#include <algorithm>
#include <cstdlib>
#include <cstring>
#define maxn 5000+10
typedef struct Point
{
int x,y;
}point;
typedef struct Line
{
point a,b;
}Line;
int ans[maxn];
int n;
Line line[maxn];
using namespace std;
int cross(point p0, point p1, point p2) //p0,p1是线段,p2是待判断的点
{
return (p2.x - p0.x)*(p1.y - p0.y)-(p1.x - p0.x)*(p2.y - p0.y);
}
void binsearch(point toy) //搜索并利用叉积进行判断
{
int l,r,mid;
l=0;
r=n-1;
while(l<r)
{
mid=(r+l)/2;
if(cross(line[mid].b,line[mid].a,toy)<0)
r=mid;
else
l=mid+1;
}
if(cross(line[l].b,line[l].a,toy)<0)
ans[l]++;
else
ans[l+1]++;
}
int main()
{
point toy;
int m,x1,y1,x2,y2;
int u,l;
int xj,yj;
while(scanf("%d",&n) && n!=0)
{
scanf("%d%d%d%d%d",&m,&x1,&y1,&x2,&y2);
memset(ans,0,sizeof(ans));
for(int i=0;i<n;i++)
{
scanf("%d%d",&u,&l);
line[i].a.x=u;
line[i].a.y=y1;
line[i].b.x=l;
line[i].b.y=y2;
}
for(int i=0;i<m;i++)
{
scanf("%d%d",&xj,&yj);
point toy;
toy.x=xj;
toy.y=yj;
binsearch(toy);
}
for(int i=0;i<=n;i++)
printf("%d: %d\n",i,ans[i]);
cout<<endl;
}
}