您的位置:首页 > 其它

向量的叉积 POJ 2318 TOYS & POJ 2398 Toy Storage

2015-04-01 11:27 477 查看
POJ 2318:

题目大意:给定一个盒子的左上角和右下角坐标,然后给n条线,可以将盒子分成n+1个部分,再给m个点,问每个区域内有多少各点

这个题用到关键的一步就是向量的叉积,假设一个点m在 由abcd围成的四边形区域内,那么向量ab, bc, cd, da和点的关系就是,点都在他们的同一侧,我是按照逆时针来算的,所以只需要判断叉积是否小于0就行了。还有一个问题就是这个题要求时间是2s,所以直接找,不用二分也能过,不过超过1s了,最好还是二分来做,二分时间170ms,二分的时候要把最左边的一条边和最右边的一条边都要加到数组中去

代码一(直接找区域)

#include<iostream>
#include <cstdio>
#include <string.h>
#include <algorithm>
using namespace std;
const int N = 5500;
struct point{
int x, y;
};
struct Edge{
point Start, End;
};
Edge edge
;
int n, m, ans
, res
;
point upper_left, lower_left, upper_right, lower_right, p
;//各个角
bool cmp(Edge e1, Edge e2)
{
if (e1.Start.x != e2.Start.x)
return e1.Start.x < e2.Start.x;
return e1.End.x < e2.End.x;
}
double direction(point a, point b, point c)//判断方向,判断点c在向量ab的哪一侧,如果返回是负值则在逆时针那侧
{
point t1, t2;
t1.x = c.x - a.x; t1.y = c.y - a.y;
t2.x = b.x - a.x; t2.y = b.y - a.y;
return (t1.x * t2.y * 1.0 - t1.y * t2.x * 1.0);
}

void dichotomization_edge(point tmp)
{
int left, right, mid;
left = 0; right = n + 1; mid = (left + right) >> 1;
while (left < right)
{
if (left + 1 == right)
{
ans[left]++;
break;
}
double d = direction(edge[mid].Start, edge[mid].End, tmp);
if (d < 0)
left = mid;
else
right = mid;
mid = (left + right) >> 1;
}
}
int main()
{
while (~scanf("%d", &n) && n)
{
memset(ans, 0, sizeof(ans));
point t1, t2;
scanf("%d %d %d %d %d", &m, &upper_left.x, &upper_left.y, &lower_right.x, &lower_right.y);
lower_left.x = upper_left.x; lower_left.y = lower_right.y;
upper_right.x = lower_right.x; upper_right.y = upper_left.y;
edge[0].Start = upper_left;
edge[0].End = lower_left;
for (int i = 1; i <= n; i++)
{
scanf("%d %d", &t1.x, &t2.x);
t1.y = upper_left.y;
t2.y = lower_right.y;
edge[i].Start = t1;
edge[i].End = t2;
}
edge[n + 1].Start = upper_right;
edge[n + 1].End = lower_right;
point tmp;
sort(edge, edge + n + 1, cmp);
for (int i = 0; i < m; i++)
{
scanf("%d %d", &tmp.x, &tmp.y);
dichotomization_edge(tmp);

}
memset(res, 0, sizeof(res));
for (int i = 0; i <= n; i++)
if (ans[i] != 0)
res[ans[i]]++;
printf("Box\n");
for (int i = 0; i < 5000; i++)
if (res[i] != 0)
printf("%d: %d\n", i, res[i]);
}

return 0;
}


View Code
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: