【题目大意】:给出一个矩形的左上角的点(x1,y1)以及右下角的点(x2,y2),并给出n条线段,线段表示为(l,y1),(r,y2),用于将矩形切割成n+1块,分别标记为0到n。再给出m个点,求举行的每一块分别包含几个点。
【解题思路】:已知给出三个点a,b,c,通过叉积可以判断c在线段a,b的哪一侧,若叉积小于0,则在线段左侧,等于0,三点共线,大于0,在线段右侧。所以对于每一个点只需要找到在其右边的最左边的线段即刻。
可以先对线段的左端点进行了排序,然后求叉积,求到一个叉积<0的线段就可以了。如果写二分会快一点。
【代码】:
#include <iostream>
#include <cstdio>
#include <cstring>
#include <string>
#include <cmath>
#include <algorithm>
using namespace std;
struct Line
{
int l,r,cnt;
}line[10000];
int n,m,x1,yy1,x2,yy2,p,q;
bool cmp(const Line &a,const Line &b)
{
return min(a.l,a.r)<min(b.l,b.r);
}
inline double det(double xx1,double yy1,double xx2,double yy2)
{
return xx1*yy2-xx2*yy1;
}
void search(int p,int q)
{
for (int i=0; i<=n; i++)
{
if (det(line[i].l*1.0-p*1.0,yy1*1.0-q*1.0,line[i].r*1.0-p*1.0,yy2*1.0-q*1.0)<0)
{
line[i].cnt++;
break;
}
}
}
int main()
{
while (~scanf("%d",&n))
{
if (n==0) break;
scanf("%d%d%d%d%d",&m,&x1,&yy1,&x2,&yy2);
line[0].l=x2;
line[0].r=x2;
line[0].cnt=0;
for (int i=1; i<=n; i++)
{
scanf("%d%d",&line[i].l,&line[i].r);
line[i].cnt=0;
}
sort(line,line+n+1,cmp);
for (int i=0; i<m; i++)
{
scanf("%d%d",&p,&q);
search(p,q);
}
for (int i=0; i<=n; i++)
printf("%d: %d\n",i,line[i].cnt);
printf("\n");
}
return 0;
}
【运行结果】: