TOYS-POJ2318

本题主要是确定给定的点在那块区域。原题给出n条直线,将长方形分为n+1快区域。我们可以对每个给定的点来判断它在那块区域,判段方法可以根据点与直线的位置关系,具体如下,对于点(x0,y0)和直线ax+by+c=0(a>0):

     1)若a*x0+b*y0+c=0,则点在直线上。

     2)若a*x0+b*y0+c>0,则点在直线右侧。

     3)若a*x0+b*y0+c<0,则点在直线左侧。

顺序查找点的位置必然会耗费大量的时间。所以采用二分方法,找到点所在的区间,然后累计起来。下面代码将ax+by+c=0化简为x+(b/a)y+(c/a)=0,默认x的系数为1.

#define _CRT_SECURE_NO_DEPRECATE
#include<iostream>
#include<string>
#include<queue>
#include<cmath>
#include<string.h>
#include<algorithm>
#include<vector>
using namespace std;
const int MAXN = 5001;
struct Line{
	double b, c;   //x+b*y+c=0
};
Line L[MAXN];
int Count[MAXN];
int BinFind(int x,int y,int n);
int main(){
	int x1, y1, x2, y2,s,t,n,m,i,x,y,id,c=1;
	while (scanf("%d", &n)&&n){
		if (c != 1)  //控制下格式
			cout << endl;
		c++;
		scanf("%d%d%d%d%d", &m, &x1, &y1, &x2, &y2);
		memset(Count, 0, sizeof(Count));
		L[0].b = 0, L[0].c = 0 - x1;   //第一条直线应该是矩形左边的一条边
		for (i = 0; i < n; i++){
			scanf("%d%d", &s, &t);
			L[i+1].b = (t - s)*1.0/(y1 - y2);
			L[i+1].c = (y2*s - t*y1)*1.0 / (y1 - y2);
		}
		L[n + 1].b = 0, L[n + 1].c = 0 - x2;      //最后一条直线应该是矩形右边那条边
		for (i = 0; i < m; i++){
			scanf("%d%d", &x, &y);
			id = BinFind(x, y, n);
			Count[id]++;
		}
		for (i = 0; i <= n; i++)
			cout << i << ": " << Count[i] << endl;
	}
	return 0;
}
int BinFind(int x, int y,int n){
	int left = 0, right = n+1; 
	while (left < right-1){    //找到的点在区间(L[left],L[rigth])之间
		int mid = (left + right) >> 1;
		if (x + L[mid].b*y + L[mid].c>0)  //点在直线右边
			left = mid;
		else
			right = mid;
	}
	return left;
}

  

posted @ 2016-07-19 23:01  曹孟德  阅读(238)  评论(0编辑  收藏  举报