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:

  1. #include <iostream>
  2. #include <array>
  3. #include <vector>
  4. #include <algorithm>
  5. #include <iterator>
  6. using namespace std;
  7. namespace cglib {
  8. template <class Type = int>
  9. struct Vec2{
  10. Type x, y;
  11. Vec2(){}
  12. Vec2(Type _x, Type _y): x(_x), y(_y){}
  13. bool operator < (const Vec2& rhs) {
  14. return y == rhs.y ? x < rhs.x : y < rhs.y;
  15. }
  16. Vec2 operator - (const Vec2& rhs) const {
  17. return Vec2(rhs.x - x, rhs.y - y);
  18. }
  19. double length2() const {
  20. return x * x + y * y;
  21. }
  22. };
  23. using vec2i = Vec2<int>;
  24. template <class Type>
  25. int to_left_test(const Type p, const Type q, const Type s) {
  26. int x = _Area(p, q, s);
  27. return x == 0 ? -1: x > 0;
  28. }
  29. template <class Type>
  30. int _Area(const Type& p, const Type& q, const Type& s) {
  31. return p.x * q.y - p.y * q.x +
  32. q.x * s.y - q.y * s.x +
  33. s.x * p.y - s.y * p.x;
  34. }
  35. bool graham_presort(std::vector<vec2i>& P, std::vector<int>& idx) {
  36. std::swap(idx[0], idx[std::min_element(P.begin(), P.end())-P.begin()]);
  37. bool is_same_line = true;
  38. std::sort(idx.begin()+1, idx.end(), [&](const int& lhs, const int& rhs)->bool{
  39. switch (to_left_test(P[idx[0]], P[lhs], P[rhs])) {
  40. case -1:
  41. return (P[lhs]-P[idx[0]]).length2() < (P[rhs]-P[idx[0]]).length2();
  42. case 0:
  43. is_same_line = false;
  44. return false;
  45. case 1:
  46. is_same_line = false;
  47. return true;
  48. }
  49. });
  50. if(!is_same_line) {
  51. for(int i = idx.size()-2; i > 0; i--) {
  52. if(to_left_test(P[idx[0]], P[*idx.rbegin()], P[idx[i]]) == -1) continue;
  53. std::reverse(idx.begin()+i+1, idx.end());
  54. break;
  55. }
  56. }
  57. return !is_same_line;
  58. }
  59. }
  60. int main() {
  61. using namespace cglib;
  62. int T, N;
  63. std::cin >> T;
  64. for(int t = 0; t < T; t++) {
  65. std::cin >> N;
  66. std::vector<vec2i> P;
  67. vec2i p;
  68. for(int i = 0; i < N; i++) {
  69. std::cin >> p.x >> p.y;
  70. P.emplace_back(p);
  71. }
  72. std::vector<int> idx(P.size());
  73. for(int i = 0; i < idx.size(); i++) idx[i] = i;
  74. std::cout << "Case " << t+1 << ":" << std::endl;
  75. if( !graham_presort(P, idx) ) {
  76. std::cout << "Impossible\n";
  77. }
  78. else {
  79. for(int i = 0; i < idx.size()-1; i++)
  80. std::cout << idx[i] << ' ';
  81. std::cout << *idx.rbegin() << std::endl;
  82. }
  83. }
  84. }

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. BufferedReader中文乱码解决

    做一个从windows cmd截获命令返回值的java程序,结果截回来的文字中所有的中文都是乱码 Microsoft Windows [�汾 6.1.7260] ��Ȩ���� (c) 2009 Mi ...

  2. jQuery2.0.0版本以后不再支持ie8的原因

    在引用jQuery时,引用高版本的Jq会在IE8下报错,在网上查了一下,jq在2.0+的版本就已经放弃对ie8的支持了.之前没有仔细研究过jq版本,借此机会去看了一下jq版本的知识.一.如何查看jq的 ...

  3. 添砖加瓦:Linux系统监测

    前言 前段时间因为项目需求,需要实时获取系统当前的运行状态,遂查阅了不少资料,基于/proc目录下的部分文件,实现了系统CPU.内存.网络和磁盘的实时监测. 一.CPU使用情况获取 获取CPU使用情况 ...

  4. 设计模式详解及PHP实现:代理模式

    [目录] 代理模式(Proxy pattern) 代理模式是一种结构型模式,它可以为其他对象提供一种代理以控制对这个对象的访问. 主要角色 抽象主题角色(Subject):它的作用是统一接口.此角色定 ...

  5. Android中使用AsyncTask

    >##今天写作业用到了AnsyncTask,记录一下自己的使用情况 >###1.Android.os.AsyncTask类 >  1.AsyncTask类对线程间通讯进行了包装,我们 ...

  6. Hadoop环境搭建问题总结

    最近抽空搭建了Hadoop完全分布式环境,期间遇到了很多问题,大部分问题还是可以在网上搜到的,这里说下自己遇到的两个没有找到结果的问题吧. 1.启动时报:没有那个文件或目录 原因:三台机器的用户名不一 ...

  7. Vue组件传递数据

    组件命名 1.字母全小写且必须包含一个连字符 my-componnect 2.使用 kebab-case(短横线分隔命名) 定义一个组件时,你也必须在引用这个自定义元素时使用 kebab-case,例 ...

  8. 微信小程序开发,如何优雅地兼容

    小程序的功能不断的增加,但是旧版本的微信客户端并不支持新功能,所以在使用这些新能力的时候需要做兼容. 关于单个 API 如何兼容,微信官方提供了兼容文档,因此我们这里不再赘述.下面主要讨论在整个项目如 ...

  9. 关于org.apache.ibatis.binding.BindingException: Invalid bound statement (not found): com.atguigu.crud.dao.DepartmentMapper.insertSelective的错误

    今天我在使用mybatis逆向工程的时候,由于一个疏忽字打错了..结果花了一早上才把错误找全..广大小伙伴们一定要小心啊(能复制粘贴就别手打) 关于org.apache.ibatis.binding. ...

  10. Mysql数据库定时全库备份

    如下脚本用于mysql全库定时备份 mysql_dump_script.sh #!/bin/bash #保存备份个数,最多保留4个文件 number=4 #备份保存路径 backup_dir=/db/ ...