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. js javascript 获取url,获得当前页面的url,静态html文件js读取url参数

    获得当前页面的url window.location.href 静态html文件js读取url参数 location.search; //获取url中"?"符后的字串 下边为转载的 ...

  2. 扎心!来自互联网er的2019年度总结,看完笑着流泪……

    转眼2019年已经接近尾声,又到了年度总结的时候了.过去一年,你加了多少班,熬了多少夜,回想起来历历在目.互联网人2019年度总结,看完扎心了-- 01 - 这一年里 你一共提了275个需求 其中27 ...

  3. (转)linux如何获取鼠标相对位置信息

    #include <stdio.h> #include <stdlib.h> #include <linux/input.h> #include <fcntl ...

  4. 等效燃油消耗ECMS与庞德里亚金最小值原理PMP中协同状态的关系

    今儿阅读了一篇文献——<车联网环境下并联混合动力客车控制策略优化研究>,是北理的博士所写的,内容比较翔实.主要是里面的关于ECMS和庞德里亚金最小值原理(PMP)的关系推导很让人印象深刻, ...

  5. JavaScript中如何给按钮设置隐藏与显示属性

    */ * Copyright (c) 2016,烟台大学计算机与控制工程学院 * All rights reserved. * 文件名:text.html * 作者:常轩 * 微信公众号:Worldh ...

  6. 前端分享之cookie的使用及单点登录

    cookie是什么 cookie的英文意思是饼干.在计算机术语中指服务端存放在客户端的一段数据.这段数据在客户端每次进行http请求时会自动加在http请求报文中的header上:服务端在响应时,可以 ...

  7. 彻底理解使用JavaScript 将Json数据导出CSV文件

    前言 将数据报表导出,是web数据报告展示常用的附带功能.通常这种功能都是用后端开发人员编写的.今天我们主要讲的是直接通过前端js将数据导出Excel的CSV格式的文件. 原理 首先在本地用Excel ...

  8. 使用nestjs集成grpc具体操作

    两个程序中, 提供grpc服务的称为服务端, 调用grpc服务的为客户端, 以下是grpc服务端和客户端的代码编写     1. 创建两个nestjs项目demo1(端口: 3000)和demo2(端 ...

  9. 数据库介绍以及MySQL数据库的使用

    一 数据库介绍 1.1 数据库定义 数据库就是存储数据的仓库  本质上就是一套cs结构的TCP程序   客户端连接到服务器 向服务器发送指令  完成数据的操作 1.2  常见数据库 关系型数据库 就是 ...

  10. vue cli web pack 全局引入jquery

    之前 装过,装 npm i —save  jquery  然后直接执行了第二步 往后 1,首先在 package.json 里加入, 然后 npm install 2, 在webpack.base.c ...