POJ 2318/2398 叉积性质

2318

2398

题意:给出n条线将一块区域分成n+1块空间,再给出m个点,询问这些点在哪个空间里。

思路:由于只要求相对位置关系,而对具体位置不关心,那么易使用叉积性质得到相对位置关系(左侧/右侧),再因为是简单几何线段不相较,即有序分布,那么在求在哪个区间时可以先对所有线段根据x坐标排序,使用二分减少复杂度。

/** @Date    : 2017-07-11 11:05:59
  * @FileName: POJ 2318 叉积性质.cpp
  * @Platform: Windows
  * @Author  : Lweleth ([email protected])
  * @Link    : https://github.com/
  * @Version : $Id$
  */
#include <stdio.h>
#include <iostream>
#include <string.h>
#include <algorithm>
#include <utility>
#include <vector>
#include <map>
#include <set>
#include <string>
#include <stack>
#include <queue>
//#include <bits/stdc++.h>
#define LL long long
#define PII pair
#define MP(x, y) make_pair((x),(y))
#define fi first
#define se second
#define PB(x) push_back((x))
#define MMG(x) memset((x), -1,sizeof(x))
#define MMF(x) memset((x),0,sizeof(x))
#define MMI(x) memset((x), INF, sizeof(x))
using namespace std;

const int INF = 0x3f3f3f3f;
const int N = 1e5+20;
const double eps = 1e-8;

struct Point
{
	int x, y;
	Point(){}
	Point(int xx, int yy){x = xx, y = yy;}
	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 cross(Point a, Point b)
{
	return a.x * b.y - a.y * b.x;
}

struct Line
{
	Point s, t;
	Line(){}
	Line(Point ss, Point tt){s = ss, t = tt;}
};

int JudegeCross(Point p0, Point p1, Point p2)
{
	return cross(p1 - p0, p2 - p0);
}

Line li[N];
int ans[N];
int vis[N];
int cmp(Line a, Line b)
{
	return a.s.x < b.s.x;
}

int main()
{
	int n, m, x1, x2, y1, y2;
	while(~scanf("%d", &n) && n)
	{
		MMF(ans);
		MMF(vis);
		scanf("%d%d%d%d%d", &m, &x1, &y1, &x2, &y2);
		for(int i = 0; i < n; i++)
		{
			int s, t;
			scanf("%d%d", &s, &t);
			li[i] = Line(Point(s, y1), Point(t, y2));
		}
		li[n] = Line(Point(x2, y1), Point(x2, y2));
		sort(li, li + n + 1, cmp);
		while(m--)
		{
			int x, y;
			scanf("%d%d", &x, &y);
			Point p = Point(x, y);
			int l = 0, r = n;
			int pos = 0;
			while(l <= r)
			{
				int mid = (l + r) >> 1;
				if(JudegeCross(p, li[mid].s, li[mid].t) < 0)
				{
					pos = mid;
					r = mid - 1;
				}
				else
					l = mid + 1;
			}
			ans[pos]++;
		}
		printf("Box\n");
		for(int i = 0; i <= n; i++)
			if(ans[i])
				vis[ans[i]]++;
		for(int i = 1; i <= n; i++)
			if(vis[i])
				printf("%d: %d\n", i, vis[i]);
	}
    return 0;
}
/** @Date    : 2017-07-11 11:05:59
  * @FileName: POJ 2318 叉积性质.cpp
  * @Platform: Windows
  * @Author  : Lweleth ([email protected])
  * @Link    : https://github.com/
  * @Version : $Id$
  */
#include <stdio.h>
#include <iostream>
#include <string.h>
#include <algorithm>
#include <utility>
#include <vector>
#include <map>
#include <set>
#include <string>
#include <stack>
#include <queue>
//#include <bits/stdc++.h>
#define LL long long
#define PII pair
#define MP(x, y) make_pair((x),(y))
#define fi first
#define se second
#define PB(x) push_back((x))
#define MMG(x) memset((x), -1,sizeof(x))
#define MMF(x) memset((x),0,sizeof(x))
#define MMI(x) memset((x), INF, sizeof(x))
using namespace std;

const int INF = 0x3f3f3f3f;
const int N = 1e5+20;
const double eps = 1e-8;

struct Point
{
	int x, y;
	Point(){}
	Point(int xx, int yy){x = xx, y = yy;}
	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 cross(Point a, Point b)
{
	return a.x * b.y - a.y * b.x;
}

struct Line
{
	Point s, t;
	Line(){}
	Line(Point ss, Point tt){s = ss, t = tt;}
};

int JudegeCross(Point p0, Point p1, Point p2)
{
	return cross(p1 - p0, p2 - p0);
}

Line li[N];
int ans[N];

int main()
{
	int n, m, x1, x2, y1, y2;
	while(~scanf("%d", &n) && n)
	{
		MMF(ans);
		scanf("%d%d%d%d%d", &m, &x1, &y1, &x2, &y2);
		for(int i = 0; i < n; i++)
		{
			int s, t;
			scanf("%d%d", &s, &t);
			li[i] = Line(Point(s, y1), Point(t, y2));
		}
		li[n] = Line(Point(x2, y1), Point(x2, y2));
		while(m--)
		{
			int x, y;
			scanf("%d%d", &x, &y);
			Point p = Point(x, y);
			int l = 0, r = n;
			int pos = 0;
			while(l <= r)
			{
				int mid = (l + r) >> 1;
				if(JudegeCross(p, li[mid].s, li[mid].t) < 0)
				{
					pos = mid;
					r = mid - 1;
				}
				else
					l = mid + 1;
			}
			ans[pos]++;
		}
		for(int i = 0; i <= n; i++)
		{
			printf("%d: %d\n", i, ans[i]);
		}
		printf("\n");
	}
    return 0;
}
时间: 2024-09-29 05:12:19

POJ 2318/2398 叉积性质的相关文章

POJ 2318 TOYS 叉积的应用

A - TOYS Time Limit:2000MS     Memory Limit:65536KB     64bit IO Format:%I64d & %I64u Submit Status Practice POJ 2318 Appoint description:  lijunle  (2011-07-18)System Crawler  (2016-05-08) Description Calculate the number of toys that land in each b

POJ 2318 TOYS 叉积

题意: 给出一个矩形范围,给出n条线段,这n条线段一定与矩形上下边界相交且互不相交,将矩形分成n+1个划分.给出m个玩具的坐标.求每个划分放的玩具数,玩具保证不会在线段和左右边界上. 分析: 判断点是否在两条直线中间,利用叉积,如果在两条直线间,必定会有两个叉积一个小于0,一个大于0(不能把相乘小于0作为判断条件) #include <iostream> #include <cstdio> #include <cstring> using namespace std;

POJ 2318 TOYS 叉积应用

点击打开链接 TOYS Time Limit: 2000MS   Memory Limit: 65536K Total Submissions: 11078   Accepted: 5312 Description Calculate the number of toys that land in each bin of a partitioned toy box. Mom and dad have a problem - their child John never puts his toys

poj 2318 TOYS &amp; poj 2398 Toy Storage (叉积)

链接:poj 2318 题意:有一个矩形盒子,盒子里有一些木块线段,并且这些线段坐标是按照顺序给出的, 有n条线段,把盒子分层了n+1个区域,然后有m个玩具,这m个玩具的坐标是已知的,问最后每个区域有多少个玩具 分析:从左往右,直到判断玩具是否在线段的逆时针方向为止,这个就需要用到叉积,当然可以用二分查找优化. 叉积:已知向量a(x1,y1),向量b(x2,y2),axb=x1*y2-x2*y1, 若axb>0,a在b的逆时针方向,若axb<0,则a在b的顺时针方向 注:每组数据后要多空一行

POJ 2318 TOYS(叉积+二分or暴力)

题目链接:POJ 2318 TOYS [写在前面]前几天跟队友分了方向,学渣开始进行计算几何的专题了,真是脑壳有点痛啊.但是我想做多了就没这么坑爹了 [题意]大体意思就是给你一个矩形,有被若干直线分成N个格子,给出M个点的坐标,问你每个点位于哪个格子中. [思路]其实就是点在凸四边形内的判断,然后就可以利用叉积的性质,当然可以用暴力枚举也可以过,但是时间复杂度有点高,最好是用二分求解.(一直觉得二分真是牛逼啊) 下面贴AC代码,用二分219MS就过了: 1 /* 2 ** POJ 2318 TO

POJ 2318

第一道计算几何. 二分一下用叉积来判..看了DIS上说要INT64,就改INT64了... 1 #include <iostream> 2 #include <cstdio> 3 #include <cstring> 4 #include <algorithm> 5 using namespace std; 6 const int Max=5050; 7 8 struct e{ 9 int x1,x2; 10 }edge[Max]; 11 struct c{

POJ 2318 计算几何+二分

TOYS Time Limit: 2000MS Memory Limit: 65536K Total Submissions: 10425 Accepted: 5002 Description Calculate the number of toys that land in each bin of a partitioned toy box. Mom and dad have a problem - their child John never puts his toys away when

POJ 2318 TOYS 利用叉积判断点在线段的那一侧

题意:给定n(<=5000)条线段,把一个矩阵分成了n+1分了,有m个玩具,放在为位置是(x,y).现在要问第几个位置上有多少个玩具. 思路:叉积,线段p1p2,记玩具为p0,那么如果(p1p2 ^ p1p0) (记得不能搞反顺序,不同的),如果他们的叉积是小于0,那么就是在线段的左边,否则右边.所以,可以用二分找,如果在mid的左边,end=mid-1 否则begin=mid+1.结束的begin,就是第一条在点右边的线段 #include <cstdio> #include <

POJ 2318 TOYS/POJ 2398 Toy Storage

计算几何终于开坑了... 叉积+二分. #include<iostream> #include<cstdio> #include<cstring> #include<algorithm> #define maxn 5050 using namespace std; struct point { int x,y; point (int x,int y):x(x),y(y) {} point () {} friend point operator-(point