向量的叉积 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 ...
随机推荐
- wariging for you oh~
- 理解O/R Mapping
本文的目的是以最精炼的语言,理解什么是O/R Mapping,为什么要O/R Mapping,和如何进行O/R Mapping. 什么是O/R Mapping? 广义上,ORM指的是面向对象的对象模型 ...
- php对mongo操作问题
最近由于业务需求,需要使用php对mongo做一些操作,关于mongodb,选择的版本是:MongoDB shell version: 2.0.6 MongoDB是一种文档导向数据库管理系统,由C++ ...
- Nginx源码研究六:NGINX的配置文件分析
上一篇写到nginx的各个模块的配置信息的存储结构,大体描述了对配置信息的配置项生成,定制,初始化过程.这里重点研究实现定制的过程,所谓实现定制,这里指的是,nginx系统提供使用者定义nginx的配 ...
- 习题二:string数组应用
说明: 读字符串char buf[100]="xxx:yyy:zzz:aaa:bbb" 按“:”进行分解到string数组中去 逻辑: 通过指针遍历整个字符串 遇到'\0'表示字符 ...
- 在Xcode中如何屏蔽某个源文件的编译警告信息
某些时候如果我们的源码在编译过程中出现大量的编译警告时,看起来是挺不爽的:但又确实没办法解决警告问题的时候,我们可以使用下面的方法来屏蔽指定的某个文件的所有警告信息. 1.在Xcode中选中工程文件. ...
- Hazelcase 简介
原博客地址:http://blog.csdn.net/zhu_tianwei/article/details/47984599 Hazelcast是一种内存数据网格in-memory data gri ...
- Centos6.x 64位 安装JDK
JDK下载地址: http://www.oracle.com/technetwork/cn/java/javase/downloads/jdk7-downloads-1880260-zhs.html ...
- JMS集群部署问题 java.net.ConnectException: Connection refused; No available router to destination
1:本地spring配置如下 <!-- JndiTemplate --> <bean id="jndiTpl" class="org.springfra ...
- ANDROID与.Net之间JSON实践
Asp.Net端: JsonHelper.cs using System.Runtime.Serialization.Json; using System.IO; using System.Text; ...