向量的叉积 POJ 2318 TOYS & POJ 2398 Toy Storage
POJ 2318:
题目大意:给定一个盒子的左上角和右下角坐标,然后给n条线,可以将盒子分成n+1个部分,再给m个点,问每个区域内有多少各点
这个题用到关键的一步就是向量的叉积,假设一个点m在 由abcd围成的四边形区域内,那么向量ab, bc, cd, da和点的关系就是,点都在他们的同一侧,我是按照逆时针来算的,所以只需要判断叉积是否小于0就行了。还有一个问题就是这个题要求时间是2s,所以直接找,不用二分也能过,不过超过1s了,最好还是二分来做,二分时间170ms,二分的时候要把最左边的一条边和最右边的一条边都要加到数组中去
代码一(直接找区域)
#include<iostream>
#include <cstdio>
#include <string.h>
using namespace std;
const int N = ;
struct point{
int x, y;
};
int n, m, ans[];
point upper_left, lower_left, upper_right, lower_right, p[N];
double direction(point a, point b, point c)//判断方向
{
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);
}
int main()
{
while (~scanf("%d", &n) && n)
{
memset(ans, , sizeof(ans));
int a, b;
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;
for (int i = ; i < * n; i++)
{
scanf("%d %d", &a, &b);
p[i].x = a; p[i].y = upper_left.y;
p[++i].x = b; p[i].y = lower_right.y; }
point tmp;
double d1, d2, d3, d4;
for (int i = ; i < m; i++)
{
scanf("%d %d", &tmp.x, &tmp.y);
//判断是否在第一个区域内
d1 = direction(upper_left, lower_left, tmp);
d2 = direction(lower_left, p[], tmp);
d3 = direction(p[], p[], tmp);
d4 = direction(p[], upper_left, tmp);
if (d1 <= && d2 <= && d3 <= && d4 <= )
{
ans[]++;
continue;
}
bool flag = false;
for (int j = ; j < * n - ; j += )
{
d1 = direction(p[j], p[j + ], tmp);
d2 = direction(p[j + ], p[j + ], tmp);
d3 = direction(p[j + ], p[j + ], tmp);
d4 = direction(p[j + ], p[j], tmp);
if (d1 <= && d2 <= && d3 <= && d4 <= )
{
ans[j / + ]++;
flag = true;
break;
}
}
if (flag)
continue;
//d1 = direction(p[2 * n - 2], p[2 * n - 1], tmp);
//d2 = direction(p[2 * n - 1], lower_right, tmp);
//d3 = direction(lower_right, upper_right, tmp);
//d4 = direction(upper_right, p[n * 2 - 2], tmp);
//if (d1 <= 0 && d2 <= 0 && d3 <= 0 && d4 <= 0)
ans[n]++;
}
for (int i = ; i <= n; i++)
printf("%d: %d\n", i, ans[i]);
puts("");
} return ;
}
代码二(二分法)
#include<iostream>
#include <cstdio>
#include <string.h>
using namespace std;
const int N = ;
struct point{
int x, y;
};
int n, m, ans[];
point upper_left, lower_left, upper_right, lower_right, p[N];//各个角
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(point tmp)//二分法判断在那块区间内
{
int left, right, mid;
left = ; right = n + ; mid = (left + right) >> ;
while (left < right)
{
if (left + == right)
{
ans[left]++;
break;
}
double d = direction(p[mid * ], p[mid * + ], tmp);
if (d < )
left = mid;
else
right = mid;
mid = (left + right) >> ;
}
}
int main()
{
while (~scanf("%d", &n) && n)
{
memset(ans, , sizeof(ans));
int a, b;
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;
p[] = upper_left;//将边角点加入p数组,为了二分 好计算
p[] = lower_left;
for (int i = ; i < * n + ; i++)
{
scanf("%d %d", &a, &b);
p[i].x = a; p[i].y = upper_left.y;
p[++i].x = b; p[i].y = lower_right.y; }
p[ * n + ] = upper_right;
p[ * n + ] = lower_right;
point tmp;
for (int i = ; i < m; i++)
{
scanf("%d %d", &tmp.x, &tmp.y);
dichotomization(tmp); }
for (int i = ; i <= n; i++)
printf("%d: %d\n", i, ans[i]);
puts("");
} return ;
}
POJ 2398:
这道题和上一题类似,包括主要过程也一样,但是有个条件不一样,上一个题它给的n条线时有序的,就是从左往右的,但是这个没有顺序,是随便给的,所以要把它排一下序,最后让求的,假设是一个区域内有t个点,的这样的区域有多少个,按照升序打印出来:
代码如下:
#include<iostream>
#include <cstdio>
#include <string.h>
#include <algorithm>
using namespace std;
const int N = ;
struct point{
int x, y;
};
struct Edge{
point Start, End;
};
Edge edge[N];
int n, m, ans[N], res[N];
point upper_left, lower_left, upper_right, lower_right, p[N];//各个角
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 = ; right = n + ; mid = (left + right) >> ;
while (left < right)
{
if (left + == right)
{
ans[left]++;
break;
}
double d = direction(edge[mid].Start, edge[mid].End, tmp);
if (d < )
left = mid;
else
right = mid;
mid = (left + right) >> ;
}
}
int main()
{
while (~scanf("%d", &n) && n)
{
memset(ans, , 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[].Start = upper_left;
edge[].End = lower_left;
for (int i = ; 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 + ].Start = upper_right;
edge[n + ].End = lower_right;
point tmp;
sort(edge, edge + n + , cmp);
for (int i = ; i < m; i++)
{
scanf("%d %d", &tmp.x, &tmp.y);
dichotomization_edge(tmp); }
memset(res, , sizeof(res));
for (int i = ; i <= n; i++)
if (ans[i] != )
res[ans[i]]++;
printf("Box\n");
for (int i = ; i < ; i++)
if (res[i] != )
printf("%d: %d\n", i, res[i]);
} return ;
}
向量的叉积 POJ 2318 TOYS & POJ 2398 Toy Storage的更多相关文章
- POJ 2318 TOYS && POJ 2398 Toy Storage(几何)
2318 TOYS 2398 Toy Storage 题意 : 给你n块板的坐标,m个玩具的具体坐标,2318中板是有序的,而2398无序需要自己排序,2318要求输出的是每个区间内的玩具数,而231 ...
- 简单几何(点与线段的位置) POJ 2318 TOYS && POJ 2398 Toy Storage
题目传送门 题意:POJ 2318 有一个长方形,用线段划分若干区域,给若干个点,问每个区域点的分布情况 分析:点和线段的位置判断可以用叉积判断.给的线段是排好序的,但是点是无序的,所以可以用二分优化 ...
- POJ 2318 TOYS/POJ 2398 Toy Storage
计算几何终于开坑了... 叉积+二分. #include<iostream> #include<cstdio> #include<cstring> #include ...
- POJ 2318 TOYS(叉积+二分)
题目传送门:POJ 2318 TOYS Description Calculate the number of toys that land in each bin of a partitioned ...
- poj 2398 Toy Storage(计算几何)
题目传送门:poj 2398 Toy Storage 题目大意:一个长方形的箱子,里面有一些隔板,每一个隔板都可以纵切这个箱子.隔板将这个箱子分成了一些隔间.向其中扔一些玩具,每个玩具有一个坐标,求有 ...
- poj 2318 TOYS & poj 2398 Toy Storage (叉积)
链接:poj 2318 题意:有一个矩形盒子,盒子里有一些木块线段.而且这些线段坐标是依照顺序给出的. 有n条线段,把盒子分层了n+1个区域,然后有m个玩具.这m个玩具的坐标是已知的,问最后每一个区域 ...
- poj 2318 TOYS (二分+叉积)
http://poj.org/problem?id=2318 TOYS Time Limit: 2000MS Memory Limit: 65536K Total Submissions: 101 ...
- POJ 2398 Toy Storage(计算几何,叉积判断点和线段的关系)
Toy Storage Time Limit: 1000MS Memory Limit: 65536K Total Submissions: 3146 Accepted: 1798 Descr ...
- 2018.07.03 POJ 2318 TOYS(二分+简单计算几何)
TOYS Time Limit: 2000MS Memory Limit: 65536K Description Calculate the number of toys that land in e ...
随机推荐
- C++对象数组操作误区
由于语义上的需要导致语法的上缺陷,所以导致对象数组在C++中存在陷阱. C++语境:一个基类指针或引用是可以指向派生类对象的,以此可来表现C++对运行时多态的需求: 创建一个对象数组将返回首元素的首地 ...
- nuc900 nand flash mtd 驱动
nuc900 nand flash mtd 驱动,请参考! /* * Copyright © 2009 Nuvoton technology corporation. * * Wan ZongShun ...
- Thinkphp 验证码、文件上传
一.验证码 验证码参数 例题:登录时验证下验证码 LoginController.class.php <?php namespace Home\Controller; use Think\Con ...
- POJ1700:Crossing River(过河问题)
POJ1700 题目链接:http://poj.org/problem?id=1700 Time Limit:1000MS Memory Limit:10000KB 64bit IO ...
- Swift互用性:与 C的API交互(Swift 2.0版)-b
节包含内容: 基本数据类型(Primitive Types) 枚举(Enumerations) 指针(Pointer) 全局常量(Global Constants) 预处理指令(Preprocesso ...
- Mifare 0简介
Mifare UltraLight又称为MF0,从UltraLight(超轻的)这个名字就可以看出来,它是一个低成本.小容量的卡片.低成本,是指它是目前市场中价格最低的遵守ISO14443A协议的芯片 ...
- CentOS下安装配置Cacti
cacti简介 随着公司规模扩大,服务器也日渐增多,对服务器集群的网络流量和服务器性能实时监测显得愈发重要.开源阵营中常用有MRTG(MultiRouter Traffic Grapher)--基于S ...
- 转:使用Jazz Automation编写自动化测试
Jazz Automation介绍 Jazz Automation是一个测试框架,构建它的目的是为所有类型的Web系统或者静态网站自动化同时加速验收/功能测试.它还能够容易地实现自动化集成测试.以前的 ...
- mongoose CastError: Cast to ObjectId failed for value
restfull路由如下: router.get('/:id', controller.show); mongoes代码如下: exports.show = function(req, res) { ...
- 【HDOJ】1053 Entropy
构造huffman编码,果断对字符进行状态压缩. #include <iostream> #include <cstdio> #include <cstring> ...