<题目链接>
题目大意:
给出矩形4个点和n个挡板俩顶点的位置,这n个挡板将该矩形分成 n+1块区域,再给你m个点的坐标,然你输出每个区域内有几个点。
解题思路:
用叉乘即可简单判断点与直线的位置关系,对每一个点,遍历挡板,直到找到符合的区间为止。
#include <cstdio> #include <iostream> #include <algorithm> #include <cstring> using namespace std; const int maxn=5000+100; int map[maxn+100]; int n,m; struct Point { int x,y; Point(int a=0,int b=0):x(a),y(b){} Point operator - (const Point&b)const { return Point(x-b.x,y-b.y); } int operator ^(const Point&b)const //重载叉乘符号 { return x*b.y-y*b.x; //两向量叉乘公式 } }; struct Line { Point a,b; Line(){} Line(Point m,Point n):a(m),b(n){} }; Line arr[maxn+100]; Point brr[maxn+100]; // 求叉积 int Mulcross(Point p0,Point p1,Point p2) { return (p1-p0)^(p2-p0); //计算 } //不一定是这个顺序计算,只要保证两个向量有共同的顶点,和下面的>0判断相应改变即可,你可以以p0或p2为顶点 void juge(Point goal) { // 从第一条线向后遍历,如果点在该线左面,则该下标total++ for(int i=0;i<n;i++) { //这里根据叉乘判断点与直线的方向,主要的依据就是两个向量叉乘的右手定则,若朝平面下,则<0,若朝平面上则>0,然后自己画图理解一下 if(Mulcross(arr[i].b,goal,arr[i].a)>0)continue; // 如果点在挡板的右边,则继续看下一个区间是否符合 else { map[i]+=1; //如果点在挡板的左边,那么当前区间点的个数+1 return; } } // 找到最后都没找到,就是在最后一个区域 map[n]+=1; } int main() { int ncase=0; while(scanf("%d",&n)!=EOF,n) { memset(map,0,sizeof(map)); int marx1,mary1,marx2,mary2; scanf("%d%d%d%d%d",&m,&marx1,&mary1,&marx2,&mary2); for(int i=0;i<n;i++) //挡板的坐标 { int x1,x2; scanf("%d %d",&x1,&x2); arr[i].a.x=x1;arr[i].a.y=mary1; arr[i].b.x=x2;arr[i].b.y=mary2; } for(int i=0;i<m;i++) //点的坐标 { int a,b; scanf("%d %d",&a,&b); juge(Point(a,b)); //找到点的区间 } for(int i=0;i<=n;i++) { printf("%d: %d\n",i,map[i]); } printf("\n"); } return 0; }
二分查找的方法
<转载于>
#include <iostream> #include <stdio.h> #include <string.h> #include <algorithm> #include <queue> #include <map> #include <vector> #include <set> #include <string> #include <math.h> using namespace std; struct Point { int x,y; Point(){} Point(int _x,int _y) { x = _x;y = _y; } Point operator -(const Point &b)const //向量相减 { return Point(x - b.x,y - b.y); } int operator *(const Point &b)const //向量相乘 { return x*b.x + y*b.y; } int operator ^(const Point &b)const { return x*b.y - y*b.x; } }; struct Line { Point s,e; Line(){} Line(Point _s,Point _e) { s = _s;e = _e; } }; int xMult(Point p0,Point p1,Point p2) //计算p0p1 X p0p2 { return (p1-p0)^(p2-p0); } const int MAXN = 5050; Line line[MAXN]; int ans[MAXN]; int main() { int n,m,x1,y1,x2,y2; bool first = true; while(scanf("%d",&n) == 1 && n) { if(first)first = false; else printf("\n"); scanf("%d%d%d%d%d",&m,&x1,&y1,&x2,&y2); int Ui,Li; for(int i = 0;i < n;i++) { scanf("%d%d",&Ui,&Li); line[i] = Line(Point(Ui,y1),Point(Li,y2)); } line[n] = Line(Point(x2,y1),Point(x2,y2)); int x,y; Point p; memset(ans,0,sizeof(ans)); while( m-- ) { scanf("%d%d",&x,&y); p = Point(x,y); int l = 0,r = n; int tmp; while( l <= r) { int mid = (l + r)/2; if(xMult(p,line[mid].s,line[mid].e) < 0) { tmp = mid; r = mid - 1; } else l = mid + 1; } ans[tmp]++; } for(int i = 0; i <= n;i++) printf("%d: %d\n",i,ans[i]); } return 0; }
2018-08-01