Keywords: 极角排序, Simple Polygon Generation

Given set of points in the plane, your task is to draw a polygon using the points. You have to use all the points. To be more specific, each point of the set has to be a vertex of the polygon, and the polygon must not have any other vertices. No two line segments of the polygon may have any point in common, except for the middle vertex of two consecutive line segments. For example, given the points on the left-hand side, a valid polygon is shown on the right-hand side:

题意:

​ 给了一组无序的平面点集,目标是构造出一个Simple Polygon, Simple Polygon相比Polygon的定义约束是要求Polygon无边自交(题目也有具体的描述)。

分析:

​ 任意点序列看作一个Polygon。原始序列满足Simple Polygon的自交约束的对应序列可看作原始序列的特定Comparator下的排序结果。此处意味着可能存在一种Comparator, 通过其可套用通用的序列排序算法得到目标结果。

​ 答案是对标Convex Hull问题的经典算法Graham Scan的presort子算法,也就是极角排序。极角排序是二维点集有序化的一个经典思路, 普通的axis-based sort可看作极点在无穷远处的一个特例, 同时Graham Scan后部分Scan可以直接处理任意的Simple Polygon或小修后处理axis-based sorted点序列。此时有某种直观指引: 通过Graham Scan的微修版presort可以解决Simple Polygon的构造问题。

​ 多点共线(且其中一个点为极点)是极角排序需要补充定义进行处理的特殊情况, Graham Scan可将多点共线的处理延迟至Scan的实现上。补充多点共线点的偏序定义为极径增序,特例为入度方向相邻的共线区间为极径减序。

Why Impossible? All the Points are in a same line.

Code:

#include <iostream>
#include <array>
#include <vector>
#include <algorithm>
#include <iterator>
using namespace std; namespace cglib {
template <class Type = int>
struct Vec2{
Type x, y;
Vec2(){}
Vec2(Type _x, Type _y): x(_x), y(_y){}
bool operator < (const Vec2& rhs) {
return y == rhs.y ? x < rhs.x : y < rhs.y;
} Vec2 operator - (const Vec2& rhs) const {
return Vec2(rhs.x - x, rhs.y - y);
} double length2() const {
return x * x + y * y;
}
};
using vec2i = Vec2<int>; template <class Type>
int to_left_test(const Type p, const Type q, const Type s) {
int x = _Area(p, q, s);
return x == 0 ? -1: x > 0;
} template <class Type>
int _Area(const Type& p, const Type& q, const Type& s) {
return p.x * q.y - p.y * q.x +
q.x * s.y - q.y * s.x +
s.x * p.y - s.y * p.x;
} bool graham_presort(std::vector<vec2i>& P, std::vector<int>& idx) {
std::swap(idx[0], idx[std::min_element(P.begin(), P.end())-P.begin()]); bool is_same_line = true;
std::sort(idx.begin()+1, idx.end(), [&](const int& lhs, const int& rhs)->bool{
switch (to_left_test(P[idx[0]], P[lhs], P[rhs])) {
case -1:
return (P[lhs]-P[idx[0]]).length2() < (P[rhs]-P[idx[0]]).length2();
case 0:
is_same_line = false;
return false;
case 1:
is_same_line = false;
return true;
}
});
if(!is_same_line) {
for(int i = idx.size()-2; i > 0; i--) {
if(to_left_test(P[idx[0]], P[*idx.rbegin()], P[idx[i]]) == -1) continue;
std::reverse(idx.begin()+i+1, idx.end());
break;
}
}
return !is_same_line;
}
} int main() {
using namespace cglib;
int T, N; std::cin >> T;
for(int t = 0; t < T; t++) {
std::cin >> N;
std::vector<vec2i> P;
vec2i p;
for(int i = 0; i < N; i++) {
std::cin >> p.x >> p.y;
P.emplace_back(p);
}
std::vector<int> idx(P.size());
for(int i = 0; i < idx.size(); i++) idx[i] = i; std::cout << "Case " << t+1 << ":" << std::endl;
if( !graham_presort(P, idx) ) {
std::cout << "Impossible\n";
}
else {
for(int i = 0; i < idx.size()-1; i++)
std::cout << idx[i] << ' ';
std::cout << *idx.rbegin() << std::endl;
} }
}

Drawing Simple Polygon(Create Simple Polygon from unordered points by angle sorting)的更多相关文章

  1. 46 Simple Python Exercises-Very simple exercises

    46 Simple Python Exercises-Very simple exercises 4.Write a function that takes a character (i.e. a s ...

  2. how to change svg polygon size by update it's points in js

    how to change svg polygon size by update it's points in js matrixTransform https://stackoverflow.com ...

  3. css create 多边形 polygon

    案例:   代码: element.style { width: 0; height: 0; /* border-left: 50px solid transparent; */ border-rig ...

  4. libgdx 裁剪多边形(clip polygon、masking polygon)

    直接放例子代码,代码中以任意四边形为例,如果需要做任意多边形,注意libgdx不能直接用ShapeRender填充多边形,需要先切割成三角形. public static void drawClip( ...

  5. Sass与Compress实战:第三章

    概要:这一章将介绍Compass如何使Web设计中最基础的部分——布局变得简单. 本章内容: ● 网格布局的基本原理以及何时使用网格布局 ● 使用Compass时的CSS网格布局框架选项 ● 使用排版 ...

  6. Java JTS & 空间数据模型

    空间数据模型 判断两个几何图形是否存在指定的空间关系.包括: 相等(equals).分离(disjoint).相交(intersect).相接(touches).交叉(crosses).包含于(wit ...

  7. (二)在实战中使用Sass和Compass

    第三章 无需计算玩转CSS网格布局 3.1 网格布局介绍 3.2 使用网格布局 3.2.1 术语 术语名 定义 是否涉及HTML标签 列 内容度量的垂直单位 否 容器 构成一个网格布局的HTML元素 ...

  8. JTS基本概念和使用

    简介 JTS是加拿大的 Vivid Solutions公司做的一套开放源码的 Java API.它提供了一套空间数据操作的核心算法.为在兼容OGC标准的空间对象模型中进行基础的几何操作提供2D空间谓词 ...

  9. D3、EChart、HighChart绘图demol

    1.echarts:   <!DOCTYPE html>   <html>   <head>   <meta charset="utf-8" ...

随机推荐

  1. 测试用例设计经典面试题之电梯、杯子、笔、桌子、洗衣机、椅子、ATM等

    测试用例设计经典面试题之电梯.杯子.笔.桌子.洗衣机.椅子.ATM等 1.测试项目:电梯 需求测试:查看电梯使用说明书.安全说明书等 界面测试:查看电梯外观 功能测试:测试电梯能否实现正常的上升和下降 ...

  2. 接口自动化测试平台 http://120.79.232.23

    接口自动化测试平台 http://120.79.232.23 T Name Latest commit message Commit time .idea 修改自动化用例修改接口时,其他接口信息被删的 ...

  3. 公司更需要会哪种语言的工程师?​IEEE Spectrum榜单发布

    IEEE Spectrum 杂志发布了一年一度的编程语言排行榜,这也是他们发布的第四届编程语言 Top 榜. 据介绍,IEEE Spectrum 的排序是来自 10 个重要线上数据源的综合,例如 St ...

  4. 如何理解TCP的三次握手协议?

    • TCP是一个面向链接的协议,任何一个面向连接的协议,我们都可以将其类比为我们最熟悉的打电话模型. 如何类比呢?我们可以从建立和销毁两个阶段分别来看这件事情. 建立连接阶段 首先,我们来看看TCP中 ...

  5. LeetCode~移除元素(简单)

    移除元素(简单) 1. 题目描述 给定一个数组 nums 和一个值 val,你需要原地移除所有数值等于 val 的元素,返回移除后数组的新长度. 不要使用额外的数组空间,你必须在原地修改输入数组并在使 ...

  6. linux lsof常用方法

    lsof简介 lsof(list open files)是一个列出当前系统打开文件的工具,在linux环境下,任何事物都是以文件形式存在,通过文件不仅仅可以访问常规数据,还可以访问网络连接和硬件.系统 ...

  7. sql -- 获取商品分类的最新销售情况

    表设计: 需求: 1.先找出各个分类中销售的最新日期 select prod_class,max(sales_date) as sn from prod_sales group by prod_cla ...

  8. 大厂面试官最常问的@Configuration+@Bean(JDKConfig编程方式)

    大厂面试官最常问的@Configuration+@Bean(JDKConfig编程方式)   现在大部分的Spring项目都采用了基于注解的配置,采用了@Configuration 替换标签的做法.一 ...

  9. CF 1305E. Kuroni and the Score Distribution

    题目大意:题目给定两个数n和m(1<=n<=5000,0<=m<=1e9)要求构造一个数列A,A中元素 大于等于1,小于等于1e9且满足严格递增 满足ai+aj=ak的(i,j ...

  10. python正则表达式之re模块方法介绍

    python正则表达式之re模块其他方法 1:search(pattern,string,flags=0) 在一个字符串中查找匹配 2:findall(pattern,string,flags=0) ...