题目大意:
有一个矩形盒子里面有n块斜的挡板(1 ≤ n ≤ 5,000),矩形盒子左上角坐标为(x1, y1),右下角坐标为(x2, y2),接着会给出每个挡板的信息(Ui, Li),表示挡板的上端点为(Ui, y1),下端点为(Li, y2),其中保证各个挡板不相交,并且挡板信息按照从左往右的顺序依次给出,接下来给出m个点的坐标(1 ≤ m ≤ 5,000)(xi, yi),输入保证点不会落在挡板上,但是可能后落在矩形边框上,但绝不会落在矩形外。
现有多个测例,每个测例都会给出上述信息,输入以n = 0结束,对于每个测例,要求从左到右输出每个隔间中点的个数,形式为"i: n",表示第i个隔间中有n个点,每个隔间占一行,隔间编号从0 ~ n共n + 1个,每个测例之间的输出用空格隔开。
注释代码:
/*
* Problem ID : POJ 2318 TOYS
* Author : Lirx.t.Una
* Language : C++
* Run Time : 235 ms
* Run Memory : 292 KB
*/
#include <iostream>
#include <cstring>
#include <cstdio>
//挡板的最大数量
#define MAXN 5000
using namespace std;
//矩形的左上角坐标以及右下角坐标
int x1, x2;
int y1, y2;
struct Point {//表示点
//可以用来记录挡板信息
//也可以用来记录普通点的信息
//如果是挡板信息则x, y表示Ui和Li
int x, y;
Point(void) {}
Point(int xx, int yy) : x(xx), y(yy) {}
friend istream &
operator>>(istream &is, Point &p) {
is >> p.x >> p.y;
return is;
}
int
operator*(Point &p2) {//计算叉积
//左操作数为点,右操作数为挡板
//设点为p0,挡板上端点为p1,下端点为p2
Point pp1(p2.y - x, y2 - y);//得到向量p0->p2
Point pp2(p2.x - p2.y, y1 - y2);//得到向量p2->p1
return pp1.x * pp2.y - pp1.y * pp2.x;//计算向量pp1×pp2
//如果>0表示点在挡板左边否则就在挡板右边(因为后面的二分保证了叉积不是大于0就是小于0
//不可能等于0)
}
};
Point p[MAXN + 2];//n + 2块挡板,矩形左边和右边也算两个,但是不用记录因为二分查找用不到
int cnt[MAXN + 1];//记录每个隔间中点的个数
int n, m;//挡板数和点数
int
bsrch(Point &_p) {//二分查找_p点落在哪个隔间中
int lft, rht, mid;
lft = 0;
rht = n + 1;
while ( lft + 1 < rht ) {//规定左右最小间距为1,这样就永远都不会查到矩形左右两边了
//也就避免了检验叉积为0的特殊情况了
mid = ( lft + rht ) >> 1;
if ( _p * p[mid] > 0 ) rht = mid;//在mid左边
else lft = mid;//右边
}
return lft;//隔间号和左挡板一致
}
int
main() {
int i;
Point _p;//点
while ( scanf("%d", &n), n ) {
memset(cnt, 0, sizeof(cnt));
scanf("%d%d%d%d%d", &m, &x1, &y1, &x2, &y2);
for ( i = 1; i <= n; i++ ) cin >> p[i];
while ( m-- ) {
cin >> _p;
cnt[ bsrch(_p) ]++;
}
for ( i = 0; i <= n; i++ )
printf("%d: %d\n", i, cnt[i]);
putchar('\n');
}
return 0;
}
无注释代码:
#include <iostream>
#include <cstring>
#include <cstdio>
#define MAXN 5000
using namespace std;
int x1, x2;
int y1, y2;
struct Point {
int x, y;
Point(void) {}
Point(int xx, int yy) : x(xx), y(yy) {}
friend istream &
operator>>(istream &is, Point &p) {
is >> p.x >> p.y;
return is;
}
int
operator*(Point &p2) {
Point pp1(p2.y - x, y2 - y);
Point pp2(p2.x - p2.y, y1 - y2);
return pp1.x * pp2.y - pp1.y * pp2.x;
}
};
Point p[MAXN + 2];
int cnt[MAXN + 1];
int n, m;
int
bsrch(Point &_p) {
int lft, rht, mid;
lft = 0;
rht = n + 1;
while ( lft + 1 < rht ) {
mid = ( lft + rht ) >> 1;
if ( _p * p[mid] > 0 ) rht = mid;
else lft = mid;
}
return lft;
}
int
main() {
int i;
Point _p;
while ( scanf("%d", &n), n ) {
memset(cnt, 0, sizeof(cnt));
scanf("%d%d%d%d%d", &m, &x1, &y1, &x2, &y2);
for ( i = 1; i <= n; i++ ) cin >> p[i];
while ( m-- ) {
cin >> _p;
cnt[ bsrch(_p) ]++;
}
for ( i = 0; i <= n; i++ )
printf("%d: %d\n", i, cnt[i]);
putchar('\n');
}
return 0;
}