题目链接:http://poj.org/problem?id=2318
题意:
一个箱子,被n个板分为n+1块,标号为0~n已知盒子左上角和右下角的坐标及每个板上下两端的横坐标(板不会交错,且按顺序给出)然后给出玩具的坐标,统计每块空间内玩具个数(保证玩具一定落在空间内)
5 6 0 10 60 0
3 1
4 3
6 8
10 10
15 30
1 5
2 1
2 8
5 5
40 10
7 9
4 10 0 10 100 0
20 20
40 40
60 60
80 80
5 10
15 10
25 10
35 10
45 10
55 10
65 10
75 10
85 10
95 10
0
多个样例,第一行n m x1 y1 x2 y2表示n条线段,m个玩具,左上角和右下角坐标。
下面n行是n条线段的上端点和下端点的x坐标。
在下面m行是m个玩具的坐标。
二维叉积判断在线段的哪一侧,然后二分查找即可。二分不好写啊,,,要多调一调。
p2p1(向量)×p2p0>0表示p0在p1p2的左面,<0表示在右面。
#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <vector>
#include <queue>
#include <cmath>
using namespace std;
const double eps = 1e-8;
const double PI = acos(-1.0);
int sgn(double x) {
if(fabs(x) < eps)return 0;
if(x < 0)return -1;
else return 1;
}
struct Point {
double x,y;
Point(){}
Point(double _x,double _y) {
x = _x;y = _y;
}
Point operator -(const Point &b)const {
return Point(x - b.x,y - b.y);
}
double operator ^(const Point &b)const {
return x*b.y - y*b.x;
}
double operator *(const Point &b)const {
return x*b.x + y*b.y;
}
void transXY(double B) {
double tx = x,ty = y;
x = tx*cos(B) - ty*sin(B);
y = tx*sin(B) + ty*cos(B);
}
};
struct Line {
Point s,e;
Line(){}
Line(Point _s,Point _e) {
s = _s;e = _e;
}
pair<int,Point> operator &(const Line &b)const {
Point res = s;
if(sgn((s-e)^(b.s-b.e)) == 0) {
if(sgn((s-b.e)^(b.s-b.e)) == 0) return make_pair(0,res);
else return make_pair(1,res);
}
double t = ((s-b.s)^(b.s-b.e))/((s-e)^(b.s-b.e));
res.x += (e.x-s.x)*t;
res.y += (e.y-s.y)*t;
return make_pair(2,res);
}
};
int main() {
int n, m, x1, y1, x2, y2;
while(~scanf("%d", &n), n) {
scanf("%d %d %d %d %d", &m, &x1, &y1, &x2, &y2);
int i, j;
Point l(x1, y1), r(x2, y2);
vector<Line> line;
int t1, t2;
for(i = 0; i < n; i++) {
scanf("%d %d", &t1, &t2);
Point p1(t1, y1), p2(t2, y2);
line.push_back(Line(p1, p2));
}
int ans[5555] = {0};
int x, y;
for(i = 0; i < m; i++) {
scanf("%d %d", &x, &y);
Point tmp(x, y);
Point v1, v2;
int l = 0, r = line.size() - 1;
while(r - 1 > l) {
int mid = (r + l) / 2;
v1 = line[mid].s - line[mid].e;
v2 = tmp - line[mid].e;
if((v1 ^ v2) > 0) {
r = mid;
}
else l = mid;
}
v1 = line[l].s - line[l].e;
v2 = tmp - line[l].e;
Point v3 = line[r].s - line[r].e;
Point v4 = tmp - line[r].e;
if((v1 ^ v2) > 0) {
ans[l]++;
}
else if((v3 ^ v4) > 0) {
ans[l + 1]++;
}
else {
ans[r + 1]++;
}
}
for(i = 0; i <= n; i++) {
printf("%d: %d\n", i, ans[i]);
}
puts("");
}
return 0;
}