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的更多相关文章

  1. POJ 2318 TOYS && POJ 2398 Toy Storage(几何)

    2318 TOYS 2398 Toy Storage 题意 : 给你n块板的坐标,m个玩具的具体坐标,2318中板是有序的,而2398无序需要自己排序,2318要求输出的是每个区间内的玩具数,而231 ...

  2. 简单几何(点与线段的位置) POJ 2318 TOYS && POJ 2398 Toy Storage

    题目传送门 题意:POJ 2318 有一个长方形,用线段划分若干区域,给若干个点,问每个区域点的分布情况 分析:点和线段的位置判断可以用叉积判断.给的线段是排好序的,但是点是无序的,所以可以用二分优化 ...

  3. POJ 2318 TOYS/POJ 2398 Toy Storage

    计算几何终于开坑了... 叉积+二分. #include<iostream> #include<cstdio> #include<cstring> #include ...

  4. POJ 2318 TOYS(叉积+二分)

    题目传送门:POJ 2318 TOYS Description Calculate the number of toys that land in each bin of a partitioned ...

  5. poj 2398 Toy Storage(计算几何)

    题目传送门:poj 2398 Toy Storage 题目大意:一个长方形的箱子,里面有一些隔板,每一个隔板都可以纵切这个箱子.隔板将这个箱子分成了一些隔间.向其中扔一些玩具,每个玩具有一个坐标,求有 ...

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

    链接:poj 2318 题意:有一个矩形盒子,盒子里有一些木块线段.而且这些线段坐标是依照顺序给出的. 有n条线段,把盒子分层了n+1个区域,然后有m个玩具.这m个玩具的坐标是已知的,问最后每一个区域 ...

  7. poj 2318 TOYS (二分+叉积)

    http://poj.org/problem?id=2318 TOYS Time Limit: 2000MS   Memory Limit: 65536K Total Submissions: 101 ...

  8. POJ 2398 Toy Storage(计算几何,叉积判断点和线段的关系)

    Toy Storage Time Limit: 1000MS   Memory Limit: 65536K Total Submissions: 3146   Accepted: 1798 Descr ...

  9. 2018.07.03 POJ 2318 TOYS(二分+简单计算几何)

    TOYS Time Limit: 2000MS Memory Limit: 65536K Description Calculate the number of toys that land in e ...

随机推荐

  1. C++ 数组作为函数参数时,传递数组大小的方法

    废话不多说,先上错误示范: void fun(int arr[arr_num]) { // ... } int main() { // ... int *arr = new int[10]; fun( ...

  2. POJ 2674 Linear world

    POJ 2674 Linear world 题目大意: 一条线上N只蚂蚁,每只蚂蚁速度固定,方向和坐标不同,碰头后掉头,求最后掉下去那只蚂蚁的时间和名字. 注意两点: 相撞可视为擦肩而过,蚂蚁们不管掉 ...

  3. (转载)最实用的清除浮动代码 css的文字过长裁剪后面跟着省略号

    css: .clearfloat:after{display:block;clear:both;content:"";visibility:hidden;} .clearfloat ...

  4. 35 Search Insert Position(找到数的位置Medium)

    题目意思:在递增数组中找到目标数的位置,如果目标数不在数组中,返回其应该在的位置. 思路:折半查找,和相邻数比较,注意边界 class Solution { public: int searchIns ...

  5. JavaScript错误处理

    JavaScript 错误 - Throw.Try 和 Catch JavaScript 测试和捕捉 try 语句允许我们定义在执行时进行错误测试的代码块. catch 语句允许我们定义当 try 代 ...

  6. PHP图形计算器(计算三角形矩形周长面积)

    运用PHP面向对象的知识设计一个图形计算器,同时也运用到了抽象类知识,这个计算器可以计算三角形的周长和面积以及矩形的周长和面积.本图形计算器有4个页面:1.PHP图形计算器主页index.php;   ...

  7. php $_server 整理

    $_SERVER['PHP_SELF'] #当前正在执行脚本的文件名,与 document root相关. $_SERVER['argv'] #传递给该脚本的参数. $_SERVER['argc'] ...

  8. JS读取文件,Javascript之文件操作 (IE)

    一.功能实现核心:FileSystemObject 对象      要在javascript中实现文件操作功能,主要就是依靠FileSystemobject对象. 二.FileSystemObject ...

  9. IOS 多个UIImageView 加载高清大图时内存管理

    IOS 多个UIImageView 加载高清大图时内存管理 时间:2014-08-27 10:47  浏览:59人 当我们在某一个View多个UIImageView,且UIImageView都显示的是 ...

  10. nginx的使用配置

    nginx为反向代理服务器,可以反向代理不同域名转向不同的具体服务器.可以用于负载压力或是同一台机器使用不同域名进行访问. 以下片段是服务器配置: #user cmcc; worker_process ...