题目大意
如图,给你一个长方形box,然后有一些隔板,给你一些点,判断是被装进几号盒子里,
题目分析
叉乘的应用问题,用二分,设在left和right区间内,然后求出mid,若与left的叉乘大于0,与mid的叉乘小于0,则在【left,mid】中,否则在另一半中。
POJ的两道题区别在于
2318所有的隔板都是按顺序给出的,然后需要求出每个隔板区间的有点的个数
2398的,板的顺序是不定的,需要先排序,然后求的是,拥有n个球的盒子个数
这里给出ZOJ 1996的代码
代码示例
#include <iostream>
#include <cstring>
#include <algorithm>
using namespace std;
struct point
{
int x,y;
};
struct note
{
point u,d;
}a[5005];
void add(int k,int xx,int yy,int xx2,int yy2);
int search(point p,int left,int right);
int cross(point p0,point p1,point p2);
bool cmp(note pp,note pp2)
{
if(pp.u.x==pp2.u.x)
return pp.d.x<pp2.d.x;
else
return pp.u.x<pp2.u.x;
}
int main()
{
int m,n,x1,x2,y1,y2,up,down,k,count[5006],cc[5006];
point p;
while(cin >> n&&n)
{
cin >> m >> x1 >> y1 >> x2 >> y2;
add(0,x1,y1,x1,y2);
add(n+1,x2,y2,x2,y1);
for(int i=1;i<=n;i++)
{
cin >> up >> down;
add(i,up,y1,down,y2);
}
sort(a+1,a+n+1,cmp);
memset(count,0,sizeof(count));
memset(cc,0,sizeof(cc));
for(int i=1;i<=m;i++)
{
cin >> p.x >> p.y;
k=search(p,0,n+1);
count[k]++;
}
for(int i=0;i<=n;i++)
{
if(count[i]!=0)
cc[count[i]]++;
}
cout << "Box" << endl;
for(int i=0;i<=5000;i++)
if(cc[i]!=0)
cout << i << ": " << cc[i] << endl;
}
return 0;
}
void add(int k,int xx,int yy,int xx2,int yy2)
{
a[k].u.x=xx;
a[k].u.y=yy;
a[k].d.x=xx2;
a[k].d.y=yy2;
}
int search(point p,int left,int right)
{
int mid=(left+right)/2;
if(left+1>=right)
return left;
if(cross(p,a[mid].u,a[mid].d)<0&&(cross(p,a[left].u,a[left].d)>0))
return search(p,left,mid);
else
return search(p,mid,right);
}
int cross(point p0,point p1,point p2)
{
int dx1,dx2,dy1,dy2;
dx1=p1.x-p0.x;
dy1=p1.y-p0.y;
dx2=p2.x-p0.x;
dy2=p2.y-p0.y;
return (dx1*dy2-dx2*dy1);
}