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; }