POJ2318:二分+叉积

本文介绍了解决POJ2318问题的方法,该问题是关于利用n个纸板将矩形区域划分,并随机放置m个玩具,然后通过二分查找确定每个玩具所在的区域编号,最终统计每个区域中玩具的数量。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

POJ2318

题解:

  • n个纸板把矩形分成(n+1)个区域,m个玩具随机仍在里面,求每个区域的玩具的个数,区域编号从0开始到n。
  • 二分查找点在哪个位置。如果点P在某条线段AB的左边(A在上面,B在下面),那么PA×PB<0。二分查找最近的线段的左边。

代码

#include <iostream>
#include <cstdio>
#include <algorithm>
#include <cstring>
#include <vector>
using namespace std;
int const N = 5000 + 10;
int n,m,x1,y1,x2,y2;
int sum[N];
typedef struct Point{
	int x,y;
}Vector;
Vector up[N],down[N];
int cross(Vector a,Vector b){
	return a.x * b.y - a.y * b.x;
}
bool judge(int a,int b,int i){   
	Vector v1 = (Vector){up[i].x - a,up[i].y - b};
	Vector v2 = (Vector){down[i].x - a,down[i].y - b};
	return cross(v1,v2) < 0;
}
int solve(int a,int b){
	int l = 1,	r = n,	ans = n+1;
	while(l <= r){
		int mid = (l + r) >> 1;
		if(judge(a,b,mid)){    //如果(a,b)在线段mid的左边
			ans = mid;
			r = mid - 1;
		}else{
			l = mid + 1;
		}
	}
	return ans - 1;
}
int main(){
	while(~scanf("%d",&n) && n){
		scanf("%d%d%d%d%d",&m,&x1,&y1,&x2,&y2);
		memset(sum,0,sizeof(sum));
		for(int i=1;i<=n;i++){
			int a,b;
			scanf("%d%d",&a,&b);
			up[i] = (Point){a,y1};
			down[i] = (Point){b,y2};
		}
		for(int i=1;i<=m;i++){
			int a,b;
			scanf("%d%d",&a,&b);
			sum[solve(a,b)]++;
		}
		for(int i=0;i<=n;i++)
			printf("%d: %d\n",i,sum[i]);
		printf("\n");
	}
	return 0;
}

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值