原题 点击打开链接
题意:有一个箱子, 被N个隔板隔开了, 有M个玩具, 在给你每个玩具的坐标, 每个个笨的坐标, 问每个隔板里卖弄有几只玩具;
输入方式, N 隔板数, M玩具数, x1,y1, x2, y2, (x1, y1)代表箱子左上角, (x2, y2)代表箱子右上角;
接下来N行, (Ui, Li)代表这个隔板的上端坐标是(Ui, y1), 下端坐标(Li, y2)
接下来M行, 代表玩具坐标;
采用二分法, 同时利用叉积的性质P = (x1, y1), Q = (x2, y2); P x Q = x1*y2 - x2*y1;如果叉积小于0, P在Q的逆时针
code
#include <cstdio>
#include <cmath>
#include <algorithm>
#include <cstring>
using namespace std;
#define N 5005
struct Segm
{
int x1, y1, x2, y2;
};
struct Point
{
int x, y;
};
Segm segm[N];
int n, m, num[N];
bool cmp(Segm a, Segm b) { return a.x1 < b.x1; }
int Cross(Point A, Segm B)
{
//printf("%d %d %d %d %d %d\n", A.x, A.y, B.x1, B.y1, B.x2, B.y2);
Point P, Q;
P.x = A.x - B.x1;
P.y = A.y - B.y1;
Q.x = B.x2 - B.x1;
Q.y = B.y2 - B.y1;
return P.x*Q.y - Q.x*P.y; //<0, left, >0 right
}
void find(Point toy)
{
int min = 0, max = n-1, mid;
while(min < max)
{
mid = (max+min) / 2;
if(Cross(toy, segm[mid]) > 0)
{
//printf("right\n");
min = mid+1;
}
else max = mid;
}
if(Cross(toy, segm[min]) < 0)
{
// printf("%d\n", min);
num[min]++;
}
else
{
// printf("%d\n", min);
num[min+1]++;
}
}
int main()
{
int x1, y1, x2, y2;
while(~scanf("%d", &n) && n)
{
int a, b;
scanf("%d %d %d %d %d", &m, &x1, &y1, &x2, &y2);
memset(num, 0, sizeof(num));
for(int i=0; i<n;i++)
{
scanf("%d %d", &a, &b);
segm[i].x1 = b;
segm[i].y1 = y2;
segm[i].x2 = a;
segm[i].y2 = y1;
}
sort(segm, segm+n, cmp);
Point toy;
for(int i=0; i<m;i++)
{
scanf("%d %d", &a, &b);
toy.x = a; toy.y = b;
find(toy);
}
for(int i=0;i<=n;i++)
{
printf("%d: %d\n", i, num[i]);
}
printf("\n");
}
return 0;
}