POJ 2318 TOYS

原题 点击打开链接

题意:有一个箱子, 被N个隔板隔开了, 有M个玩具, 在给你每个玩具的坐标, 每个个笨的坐标, 问每个隔板里卖弄有几只玩具;

输入方式, N 隔板数, M玩具数, x1,y1, x2, y2, (x1, y1)代表箱子左上角, (x2, y2)代表箱子右上角;

接下来N行, (Ui, Li)代表这个隔板的上端坐标是(Ui, y1), 下端坐标(Li, y2)

接下来M行, 代表玩具坐标;

采用二分法, 同时利用叉积的性质P = (x1, y1), Q = (x2, y2); P x Q = x1*y2 - x2*y1;如果叉积小于0, P在Q的逆时针

code

#include <cstdio>
#include <cmath>
#include <algorithm>
#include <cstring>
using namespace std;
#define N 5005
struct Segm
{
    int x1, y1, x2, y2;
};
struct Point
{
	int x, y;
};
Segm  segm[N];
int n, m, num[N];
bool cmp(Segm a, Segm b) { return a.x1 < b.x1; }
int Cross(Point A, Segm B)
{
	//printf("%d %d %d %d %d %d\n", A.x, A.y, B.x1, B.y1, B.x2, B.y2);
	Point P, Q;
	P.x = A.x - B.x1;
	P.y = A.y - B.y1;
	Q.x = B.x2 - B.x1;
	Q.y = B.y2 - B.y1;
	return P.x*Q.y - Q.x*P.y;   //<0, left, >0 right
}

void find(Point toy)
{
	int min = 0, max = n-1, mid;
	while(min < max)
	{
		mid = (max+min) / 2;
		if(Cross(toy, segm[mid]) > 0)
		{
			//printf("right\n");
			min = mid+1;
		}
		else max = mid;
	}

	if(Cross(toy, segm[min]) < 0)
	{
	//	printf("%d\n", min);
		num[min]++;
	}
	else
	{
	//	printf("%d\n", min);
		num[min+1]++;
	}
}
int main()
{
	int x1, y1, x2, y2;
	while(~scanf("%d", &n) && n)
	{
		int a, b;
		scanf("%d %d %d %d %d", &m, &x1, &y1, &x2, &y2);
		memset(num, 0, sizeof(num));
		for(int i=0; i<n;i++)
		{
			scanf("%d %d", &a, &b);
			segm[i].x1 = b;
			segm[i].y1 = y2;
			segm[i].x2 = a;
			segm[i].y2 = y1;
		}
		
		sort(segm, segm+n, cmp);
		
		Point toy;
		for(int i=0; i<m;i++)
		{
			scanf("%d %d", &a, &b);
			toy.x = a; toy.y = b;
			find(toy);
		}
		for(int i=0;i<=n;i++)
		{
			printf("%d: %d\n", i, num[i]);
		}
		printf("\n");
	}
	return 0;
}



  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值