http://poj.org/problem?id=2318
题意:
一个矩形的玩具盒子,用隔板分成很多块,每个隔板的两端分别在矩形的上下边界上,且任两个隔板不会相交。现给定矩形的左上角和右下角坐标,每个隔板两端点的坐标以及一些玩具的坐标,问每个区域内分布有多少玩具?
输入多个样例,每个样例输入6个整数,n,m,x1,y1,x2,y2,n是隔板数,m是玩具个数(x1,y1),(x2,y2)分别是矩形的左上角和右下角坐标,接下来n行,每行输入两个数Ui和Li,代表第i个隔板的上下端点分别是(Ui,y1)和(Li,y2)。隔板按照从左到右的顺序给出,并且任意两隔板不会相交。
接下来m行给出玩具坐标,玩具不会恰好落在隔板上或者矩形边界上。输入0表示输入结束。
输出每个小块中分布的玩具数目。
思路:
对于一个已知位置的玩具,可以二分找出它右边的隔板,需要判断线与点的位置关系,通过向量叉积判断即可。
PS:判断点与直线位置关系
令I=AB×BC,当I为正时,点C在AB向量所在直线的左侧;为负时,在右侧,I=0时,点C在直线AB上。
代码:
#include<iostream> #include<stdio.h> #include<stdlib.h> #include<string> #include<iomanip> #include<algorithm> #include<string.h> #include<queue> #include<cmath> #include<stack> using namespace std; const int maxn = 5010; const int inf = 0x7f7f7f7f; typedef long long ll; struct point { int x, y; point() {} point(int _x, int _y) :x(_x), y(_y) {} point operator -(const point& a) const { return point(x - a.x, y - a.y); } int operator *(const point& a) const { return x * a.y - y * a.x; } }; int n, m, x1, y11, x2, y2; int U[maxn], L[maxn]; int ans[maxn]; bool ch(int x, int y, int id) { point a = point(L[id], y2), b = point(U[id], y11);//检查编号id的隔板是否在点(x,y)的左侧 point c = point(x, y); return (c - a) * (b - a) > 0; } int find(int x, int y) { int l = 0, r = n + 1, mid; while (l < r) { mid = (l + r) >> 1; if (ch(x, y, mid)) l = mid + 1; else r = mid; } return l - 1; } int main() { while (~scanf("%d", &n), n) { memset(ans, 0, sizeof(ans)); scanf("%d%d%d%d%d", &m, &x1, &y11, &x2, &y2); U[0] = L[0] = x1, U[n + 1] = L[n + 1] = x2; for (int i = 1; i <= n; i++) scanf("%d%d", &U[i], &L[i]); int x, y; for (int i = 0; i < m; i++) { scanf("%d%d", &x, &y); ans[find(x, y)]++; } for (int i = 0; i <= n; i++) printf("%d: %d ", i, ans[i]); printf(" "); } system("pause"); return 0; }