入门第一发 了解 点,向量的表示 学会判断点与直线的位置关系
/* 输入文件包含一个或多个问题,第一行是第一个问题包含6个数,n,m,x1,x2,y1,y2,纸板分区的数目为n (0 < n <= 5000),玩具的数量是m(0<m<5000),箱子左上角的坐标为(x1,y1),右下角的坐标为(x2,y2)。 以下N行,每行包含两个整数,Ui Li,表示第i个纸板分区的结束是在坐标(UI,y1)和(Li,y2)。 你可以假设纸板分区彼此不相交,它们是从左到右按排序顺序指定的。 接下来的m行每行包含两个整数,Xj Yj指定该位置被第j个玩具落在了箱子里,玩具位置的顺序是随机的。 你可以假设没有玩具会准确地落在硬纸板的隔板上或盒子的外面(就是所有玩具肯定都会掉进箱子里面), 输入由一个单0组成的行终止。 */ #include<cstdio> #include<cstring> #define db double using namespace std; const int N=5050; const db eps=1e-7; struct Point // 点的定义 { db x,y; Point(db x=0,db y=0) : x(x),y(y) {}; }; typedef Point Vector ; // 向量的定义 和点一样 表示一个 (0,0) -> (x,y) 的向量 int n,m,x,y,x1,y1,x2,y2,u[N],l[N],num[N]; Vector operator + (Vector A,Vector B) {return Vector(A.x+B.x,A.y+B.y);} // 向量加法 Vector operator - (Vector A,Vector B) {return Vector(A.x-B.x,A.y-B.y);} // 向量减法 Vector operator * (Vector A, db p) {return Vector(A.x*p,A.y*p);} // 向量乘法 Vector operator / (Vector A, db p) {return Vector(A.x/p,A.y/p);} // 向量除法 db cross(Vector A,Vector B) {return A.x*B.y-A.y*B.x;} //叉积 bool check(int i) // 点 (x,y) 和 线(u[i],y1)(l[i],y2) 叉积 (位置关系) { db res=cross(Vector(x-l[i],y-y2),Vector(u[i]-l[i],y1-y2)); // 同时减去 (l[i],y2)这个点 他们的相对位置不改变 // 相当于把向量的一个端点(l[i],y2)移动到原点 点(x,y)随之移动相应的距离 if(res>-eps) return 1; // 顺时针方向 即左边 return 0; // 逆时针方向 即右边 } int main() { while(scanf("%d",&n)&&n) { memset(num,0,sizeof(num)); scanf("%d%d%d%d%d",&m,&x1,&y1,&x2,&y2); for(int i=0;i<n;i++) scanf("%d%d",&u[i],&l[i]); for(int i=1;i<=m;i++) { scanf("%d%d",&x,&y); int L=0,R=n-1; while(L<=R) { int mid=(L+R)>>1; if(check(mid)) L=mid+1; else R=mid-1; } num[L]++; } for(int i=0;i<=n;i++) printf("%d: %d\n",i,num[i]); putchar('\n'); } return 0; }