原题 点击打开链接
题意:有一个箱子, 被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 ", 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 "); min = mid+1; } else max = mid; } if(Cross(toy, segm[min]) < 0) { // printf("%d ", min); num[min]++; } else { // printf("%d ", 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 ", i, num[i]); } printf(" "); } return 0; }