poj 3293 Rectilinear polygon
| Time Limit: 1000MS | Memory Limit: 65536K | |
| Total Submissions: 2125 | Accepted: 249 |
Description
Given is n points with integer coordinates in the plane. Is it is possible to construct a simple, that is non-intersecting, rectilinear polygon with the given points as vertices? In a rectilinear polygon there are at least 4 vertices and every edge is either horizontal or vertical; each vertex is an endpoint of exactly one horizontal edge and one vertical edge. There are no holes in a polygon.
Input
The first line of input is an integer giving the number of cases that follow. The input of each case starts with an integer 4 ≤ n ≤ 100000 giving the number of points for this test case. It is followed by n pairs of integers specifying the x and y coordinates of the points for this case.
Output
The output should contain one line for each case on input. Each line should contain one integer number giving the length of the rectilinear polygon passing throught the given points when it exists; otherwise, it should contain -1.
Sample Input
1
8
1 2
1 0
2 1
2 2
3 2
3 1
4 0
4 2
Sample Output
12
题意:平面图上给出一些点的坐标,通过这些点希望构成一类多边形,多边形中间没有洞,并且每个点是且仅是该多边形的一条横边和一条竖边的端点,且横边竖边不相交(横竖边共用一个端点的情况除外),若给出的那些点能构成符合要求的多边形,
那么计算多边形的周长,否则输出-1.
思路:平面扫描,按照x轴扫描可以获得所有竖边的长度和,按y轴的同理,先讨论x轴的情况,将点按照x坐标大小排序后,同一列上的点按照y坐标从小到大排序,之后再观察多边形每一列的特性,可以发现每一列上点必定偶数个,相邻两个配对可以成为一条边,若出现奇数条边,肯定是构不成多边形的。按y轴扫描
也是相同做法。其次还要判断是否有横竖边相交的情况以及是否有洞(图是否连通)即可。
AC代码:
#define _CRT_SECURE_NO_DEPRECATE
#include<iostream>
#include<stdio.h>
#include<algorithm>
#include<queue>
#include<set>
#include<vector>
#include<cstring>
#include<string>
#include<functional>
#include<cmath>
#include<stack>
using namespace std;
const int N_MAX = + ;
#define INF 0x3f3f3f3f
#define EPS 1e-10
#define equals(a,b) (fabs(a-b)<EPS)
static const int COUNTER_CLOCKWISE = -;
static const int CLOCKWISE = ;
static const int ONLINE_BACK = ;
static const int ONLINE_FRONT = -;
static const int ON_SEGMENT = ; int n;//点的数量 int link_x[N_MAX], link_y[N_MAX]; class point {
public:
int x, y;
int id;
point(int x = , int y = , int id = ) :x(x), y(y), id(id) {} int get(const bool& is_x) {//用于双向扫描
return is_x ? x : y;
}
void link(const point& b, const bool& is_x) {//当前点与点b相连,!!!!不是必须
(is_x ? link_x[id] : link_y[id]) = b.id;
(is_x ? link_x[b.id] : link_y[b.id]) = id;
}
int get_link(const bool &is_x) {
return is_x ? link_x[id] : link_y[id];
} point operator +(point p) { return point(x + p.x, y + p.y); }
point operator -(point p) { return point(x - p.x, y - p.y); }
point operator *(double a) { return point(a*x, a*y); }
point operator /(double a) { return point(x / a, y / a); }
double norm() { return x*x + y*y; }
double abs() { return sqrt(norm()); }
bool operator<(const point&p)const {
return x != p.x ? x < p.x : y < p.y;
}
bool operator ==(const point&p)const {
return x == p.x && y == p.y;
}
double dot(point p) {
return x*p.x + y*p.y;
}
double det(point p) {
return x*p.y - y*p.x;
}
}P[N_MAX]; bool is_x;
bool cmp( point a, point b) {
int ax = a.get(is_x);
int ay = a.get(!is_x);
int bx = b.get(is_x);
int by = b.get(!is_x);
if (ax != bx) {
return ax < bx;
}
else return ay < by;
} typedef point Vector;
struct Segment {
point p1, p2;
Segment(point p1 = point(), point p2 = point()) :p1(p1), p2(p2) {}
};
//vector<Segment>S_x;
Segment S_x[N_MAX]; typedef Segment line;
class Circle {
public:
point c;
double r;
Circle(point c = point(), double r = 0.0) :c(c), r(r) {} };
typedef vector<point>Polygon;
//p在线段s上的投影
point project(Segment s, point p) {
Vector base = s.p2 - s.p1;
double r = base.dot(p - s.p1) / base.norm();
return s.p1 + base*r;
}
//点p关于直线s的对称点
point reflect(Segment s, point p) {
return p + (project(s, p) - p)*2.0;
}
//点与点间距离
double getDistance(point a, point b) {
return (a - b).abs();
}
//点到直线距离
double getDistanceLP(line l, point p) {
return fabs((l.p1 - l.p2).det(p - l.p1)) / ((l.p2 - l.p1).abs());
}
//点到线段的距离
double getDistanceSP(Segment s, point p) {
if ((s.p2 - s.p1).dot(p - s.p1) < 0.0)return (p - s.p1).abs();
if ((s.p1 - s.p2).dot(p - s.p2) < 0.0)return (p - s.p2).abs();//!!!!!
return getDistanceLP(s, p);
}
//判断线段p0p1与线段p0p2的旋转关系
int ccw(point p0, point p1, point p2) {
Vector a = p1 - p0;
Vector b = p2 - p0;
if (a.det(b) > EPS)return COUNTER_CLOCKWISE;
if (a.det(b) < -EPS)return CLOCKWISE;
if (a.dot(b) < -EPS)return ONLINE_BACK;
if (a.norm() >= b.norm())return ON_SEGMENT;//!!
return ONLINE_FRONT;
}
//判断线段p1p2与p3p4是否相交
bool intersect(point p1, point p2, point p3, point p4) {
return (ccw(p1, p2, p3)*ccw(p1, p2, p4) < &&//!!!
ccw(p3, p4, p1)*ccw(p3, p4, p2) < );
} //线段是否相交
bool intersect(Segment s1, Segment s2) {
return intersect(s1.p1, s1.p2, s2.p1, s2.p2);
} typedef vector<point>Polygon; bool judge_intersect(const Segment&a,const int&amount) {
int y = a.p1.y, x1 = a.p1.x, x2 = a.p2.x;
for (int i = ; i <amount;i++) {
if (y > S_x[i].p1.y&&y < S_x[i].p2.y&&x1<S_x[i].p1.x&&x2>S_x[i].p2.x) {
return true;
}
}
return false;
} int traverse(int&amount) {//返回总长度,不符条件-1
sort(P, P + n, cmp);//!!!!每次扫描前先排序
int count = , sum = ;
for (int i = ; i < n; i++) {//遍历每一个点
if (P[i].get(is_x)!=P[i - ].get(is_x)) {//到了新的扫描层
if (count & )return -;
count = ;
}
else {
count++;
if (!(count & )) {
sum += P[i].get(!is_x) - P[i - ].get(!is_x);
P[i].link(P[i - ], is_x); if (is_x) {//若是横向扫描,直接记录连接好的线段
S_x[amount++]=Segment(P[i-], P[i]); }
else {//竖向扫描,判断当前连接线段是否和上面的记录的线段相交
if (judge_intersect(Segment(P[i-],P[i]),amount)) {
return -;
}
}
}
}
}
return sum;
} int solve() {
int amount = ;//记录连边的个数
is_x=;
int num_x = traverse(amount);
if (num_x == -)return -;//!!!! is_x =;
int num_y = traverse(amount);
if (num_y == -)return -;
int loop = ,count=; do {//判断不联通的图
loop = is_x ? link_x[loop] : link_y[loop];
count++;
is_x = !is_x;
} while (loop != ); if (count != n)return -;
return num_x + num_y;
} int main() {
int t;
scanf("%d", &t);
while (t--) { scanf("%d", &n);
for (int i = ; i < n; i++) {
int x, y;
scanf("%d%d", &x, &y);
P[i] = point(x, y, i);
}
printf("%d\n",solve());
}
return ;
}
poj 3293 Rectilinear polygon的更多相关文章
- POJ 3293 Rectilinear polygon(几何基础)
[题目链接] http://poj.org/problem?id=3293 [题目大意] 给出一些点,每个点只能向外引出一条平行X轴,和Y轴的边, 问能否构成一个闭多边形,如果能,返回多边形的总边长, ...
- poj 2007 Scrambled Polygon(极角排序)
http://poj.org/problem?id=2007 Time Limit: 1000MS Memory Limit: 30000K Total Submissions: 6701 A ...
- POJ 1179 IOI1998 Polygon
Time Limit: 1000MS Memory Limit: 10000K Total Submissions: 5472 Accepted: 2334 Description Polyg ...
- POJ 2007 Scrambled Polygon 凸包
Scrambled Polygon Time Limit: 1000MS Memory Limit: 30000K Total Submissions: 7214 Accepted: 3445 ...
- POJ 2007 Scrambled Polygon [凸包 极角排序]
Scrambled Polygon Time Limit: 1000MS Memory Limit: 30000K Total Submissions: 8636 Accepted: 4105 ...
- ●POJ 2007 Scrambled Polygon
题链: http://poj.org/problem?id=2007 题解: 计算几何,极角排序 按样例来说,应该就是要把凸包上的i点按 第三像限-第四像限-第一像限-第二像限 的顺序输出. 按 叉积 ...
- POJ 2007 Scrambled Polygon 极角序 水
LINK 题意:给出一个简单多边形,按极角序输出其坐标. 思路:水题.对任意两点求叉积正负判断相对位置,为0则按长度排序 /** @Date : 2017-07-13 16:46:17 * @File ...
- 简单几何(极角排序) POJ 2007 Scrambled Polygon
题目传送门 题意:裸的对原点的极角排序,凸包貌似不行. /************************************************ * Author :Running_Time ...
- POJ 2007 Scrambled Polygon (简单极角排序)
题目链接 题意 : 对输入的点极角排序 思路 : 极角排序方法 #include <iostream> #include <cmath> #include <stdio. ...
随机推荐
- 01_2Java开发环境的下载 安装 配置
01_2Java开发环境的下载 安装 配置 l 配置Java开发环境步骤(WindowsXP) l 下载并按照最新版本的J2SDK l 设置Windows环境变量 l 选择合适的文本编辑器或使用集成开 ...
- cocos2dx for lua 截屏功能
cocos2dx的utils类中包含截图功能,使用方法如下: cc.utils:captureScreen(function(successed,outputFile)--第一个参数是截图成功或者失败 ...
- CF-1140 E - Palindrome-less Arrays
题意:给定一个没有填完的序列,数值为-1表示你可以用 1~k 中的数字去覆盖它,求将该序列填充后,不存在长度为奇数的回文串的方案数 分析: 使之不存在长度为奇数的回文串,只需要满足不存在长度为3的回文 ...
- [BZOJ] 1520: [POI2006]Szk-Schools
费用流解决. abs内传不了int..CE一次 #include<iostream> #include<cstring> #include<cstdio> #inc ...
- CentOS7下Mysql5.7主从数据库配置
本文配置主从使用的操作系统是Centos7,数据库版本是mysql5.7. 准备好两台安装有mysql的机器(mysql安装教程链接) 主数据库配置 每个从数据库会使用一个MySQL账号来连接主数据库 ...
- 进入JVM的世界:《深入理解JVM虚拟机》-- 思维导图
进入JVM的世界:<深入理解JVM虚拟机>-- 思维导图 之前一直都是零零散散的看了些JVM的知识,心想这样不行啊!于是便抽空看了一下这本神书,阅罢,醍醐灌顶.豁然开朗.真正的是知其然,更 ...
- MYSQL安装与库的基本操作
mysql数据库 什么是数据库 # 用来存储数据的仓库 # 数据库可以在硬盘及内存中存储数据 数据库与文件存储数据区别 数据库本质也是通过文件来存储数据, 数据库的概念就是系统的管理存储数据的文件 数 ...
- MongoDB之Replica Sets环境搭建
最近学习MongoDB,这两天在搭建复制集的时候碰到了不少问题,也踩了好多坑,现在在这里记录下来,以供自己和他人参考 (因为本人是初学者,所以遇到的问题也会比较初级,所以本文也比较适合初学者查阅) 背 ...
- #1 add life to static pages && connect to MySQL
由于实验室 Project 中需要用到PHP, 之前也没接触过 PHP, 因此把 编程入门 <Head Fist PHP & MySQL >找来花了四五天快速过了一遍. 现在想把书 ...
- HDU 4348 To the moon 主席树
题意: 给出一个长度为\(n(n \leq 10^5)\)的序列,最开始时间\(t=0\),支持下面几个操作: \(C \, l \, r \, d\):将区间\([l,r]\)每个数都加上\(d\) ...