题目链接http://acm.hdu.edu.cn/showproblem.php?pid=6631

题意:共\(T\)组数据,每组数据给出\(n\)个点的坐标,这\(n\)个点按顺序给出,相邻的点相连后构成一个简单多边形。询问能否在最多移动一个点的情况下新构成的图形为轴对称图形。

分析:如下图所示,一个轴对称图形的对称轴仅存在两种情况,一是相邻两点的中垂线,二是相隔一点的中垂线。

因此我们只需要对相邻点和相隔一点的点对求中垂线,分别判断是否能够仅移动一个点使得图形成为轴对称图形即可。如下图,多边形\(ABCDX\)可以转变为\(ABCDE\),多边形\(A_1B_1C_1YE_1\)可以转变为\(A_1B_1C_1D_1E_1\)。因此判定能否构成轴对称图形的条件即为轴线两侧的对应点对不关于轴线对称的数量是否\(<2\)。如下图的\(ABCDX\)仅具有一组点对\((X,X)\)不对称。

接下来我们需要解决的问题就是如何快速判定点对关于中垂线对称。如下图,若点对关于轴线对称,则必有两组点对的中点连线与这两组点的连线相互垂直。如下图若点\(N,Q\)关于点\(O,P\)形成的中垂线对称,则应有\(ST\bot NQ\)以及\(TS\bot OP\)(\(T\),\(S\)分别为中点)。

于是我们就得到了一个\(o(n^2)\)的解法,本题就轻松解决了。(大雾)

事实上这样是无法通过的,因为我们忽略了图形有可能自交的情况。如下图样例。

如图,\((D, E)\)点对不构成对称,若将\(D\)点移至\(D_1\)点,则该多边形自交,不再构成简单多边形。因此我们在点对不对称时需要加上特判。特判的方法可由下图观察得到:

我们以对称轴为界将多边形分成两部分。观察不对称的点对(红点),并且将红点与它相邻的两个点看作一个整体,当且仅当这两组点都跨过对称轴时多边形自交(跨过对称轴包括红点落在对称轴上的情况)。

 

AC代码

#include <bits/stdc++.h>
#define SIZE 1007
#define rep(i, a, b) for(int i = a; i <= b; ++i)
using namespace std;
typedef long long ll;
int t, n;
struct Point {
double x, y;
}p[SIZE], a, b, tp, mid, mx, mid2, nullp;
void io() {
ios::sync_with_stdio(false);
cin.tie(nullptr);
cout.tie(nullptr);
}
double cross(Point a, Point b, Point c) { return (b.x - a.x) * (c.y - b.y) - (b.y - a.y) * (c.x - b.x); }
double cdot(Point a, Point b, Point c) { return (b.x - a.x) * (b.x - c.x) + (b.y - c.y) * (b.y - a.y); }
int spjudge(int j, int k, Point mid, Point mid2) {
bool f1 = false, f2 = false; int num = 0;
if (cross(mid, p[j], mid2)) {
int pre = j - 1, post = j + 1;
if (pre < 1) pre += n;
if (post > n) post -= n;
if (cross(mid, p[pre], mid2)*cross(mid, p[post], mid2) < 0) f1 = true;
if (cross(mid, p[pre], mid2)*cross(mid, p[j], mid2) < 0) f1 = true;
if (cross(mid, p[post], mid2)*cross(mid, p[j], mid2) < 0) f1 = true;
}
else f1 = true;
if (cross(mid, p[k], mid2)) {
int pre = k + 1, post = k - 1;
if (pre < 1) pre += n;
if (post > n) post -= n;
if (cross(mid, p[pre], mid2)*cross(mid, p[post], mid2) < 0) f2 = true;
if (cross(mid, p[pre], mid2)*cross(mid, p[j], mid2) < 0) f2 = true;
if (cross(mid, p[post], mid2)*cross(mid, p[j], mid2) < 0) f2 = true;
}
else f2 = true;
if (f1&&f2) return 1;
else return 0;
}
bool judge1() {
rep(i, 1, n) {
int num = 0;
a = p[i]; b = p[i % n + 1];
mid.x = (a.x + b.x) / 2; mid.y = (a.y + b.y) / 2;
mid2.x = mid.x + (a.y - mid.y); mid2.y = mid.y + (mid.x - a.x);
int tt = n / 2 - 1;
if (n % 2) {
tp = p[(i + n / 2) % n + 1];
if (cross(mid, tp, mid2)) ++num;
}
int j = i - 1, k = i + 2;
while (tt--) {
if (j < 1) j += n;
if (k > n) k -= n;
mx.x = (p[j].x + p[k].x) / 2;
mx.y = (p[j].y + p[k].y) / 2;
if ((cdot(p[i], mid, mx) != 0) || (cdot(mid, mx, p[j]) != 0)) {
++num;
num += spjudge(j, k, mid, mid2);
}
--j, ++k;
}
if (num <= 1) return true;
}
return false;
}
bool judge2() {
rep(i, 1, n) {
int num = 0;
a = p[i]; b = p[(i + 1) % n + 1];
mid.x = (a.x + b.x) / 2; mid.y = (a.y + b.y) / 2;
mid2.x = mid.x + (a.y - mid.y); mid2.y = mid.y + (mid.x - a.x);
int tt = n / 2 - 1;
tp = p[i % n + 1];
if (cross(mid, tp, mid2)) ++num;
if (n % 2 == 0) {
tp = p[(i + n / 2) % n + 1];
if (cross(mid, tp, mid2)) ++num;
}
int j = i - 1, k = i + 3;
while (tt--) {
if (j < 1) j += n;
if (k > n) k -= n;
mx.x = (p[j].x + p[k].x) / 2;
mx.y = (p[j].y + p[k].y) / 2;
if ((cdot(p[i], mid, mx) != 0) || (cdot(mid, mx, p[j]) != 0)) {
++num;
num += spjudge(j, k, mid, mid2);
}
--j, ++k;
}
if (num <= 1) return true;
}
return false;
}
int main() {
io(); cin >> t;
while (t--) {
cin >> n;
rep(i, 0, 1000) p[i] = nullp;
rep(i, 1, n) cin >> p[i].x >> p[i].y;
if (n < 5) { cout << "Y\n"; continue; }
if (judge1()) cout << "Y\n";
else if (judge2()) cout << "Y\n";
else cout << "N\n";
}
}

HDU 6631 line symmetric 计算几何的更多相关文章

  1. HDU 6631 line symmetric(枚举)

    首先能想到的是至少有一对相邻点或者中间间隔一个点的点对满足轴对称,那么接下来只需要枚举剩下的点对是否满足至多移动一个点可以满足要求. 第一种情况,对于所有点对都满足要求,那么Yes. 第二种情况,有一 ...

  2. HDU 5130 Signal Interference(计算几何 + 模板)

    HDU 5130 Signal Interference(计算几何 + 模板) 题目链接http://acm.hdu.edu.cn/showproblem.php?pid=5130 Descripti ...

  3. HDU 3400 Line belt (三分再三分)

    HDU 3400 Line belt (三分再三分) ACM 题目地址:  pid=3400" target="_blank" style="color:rgb ...

  4. HDU 4063 Aircraft(计算几何)(The 36th ACM/ICPC Asia Regional Fuzhou Site —— Online Contest)

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=4063 Description You are playing a flying game. In th ...

  5. HDU 5979 Convex【计算几何】 (2016ACM/ICPC亚洲区大连站)

    Convex Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/65536 K (Java/Others)Total Subm ...

  6. 三分套三分 --- HDU 3400 Line belt

    Line belt Problem's Link:   http://acm.hdu.edu.cn/showproblem.php?pid=3400 Mean: 给出两条平行的线段AB, CD,然后一 ...

  7. HDU 4606 Occupy Cities (计算几何+最短路+最小路径覆盖)

    转载请注明出处,谢谢http://blog.csdn.net/ACM_cxlove?viewmode=contents    by---cxlove 题目:给出n个城市需要去占领,有m条线段是障碍物, ...

  8. 2017 Multi-University Training Contest - Team 9 1003&&HDU 6163 CSGO【计算几何】

    CSGO Time Limit: 20000/10000 MS (Java/Others)    Memory Limit: 65536/65536 K (Java/Others)Total Subm ...

  9. HDU 5839 Special Tetrahedron 计算几何

    Special Tetrahedron 题目连接: http://acm.hdu.edu.cn/showproblem.php?pid=5839 Description Given n points ...

随机推荐

  1. Python3标准库:difflib差异计算工具

    1. difflib差异计算工具 此模块提供用于比较序列的类和函数. 例如,它可以用于比较文件,并可以产生各种格式的不同信息,包括HTML和上下文以及统一格式的差异点.有关目录和文件的比较,请参见fi ...

  2. HTML之<meta>标签全解

      一.定义 元素可提供相关页面的元信息(meta-information),比如针对搜索引擎和更新频度的描述和关键词等等. 标签位于文档的头部<head></head>标签内 ...

  3. Qt VS Tools插件官方下载及安装

    下载 官方下载地址:https://download.qt.io/development_releases/vsaddin/(国外网站直接打开超级慢) 找到对应的VS版本下载 安装 下载完成后安装,打 ...

  4. HDU 1542 Atlantis(扫描线算法)

    题意:给出n个矩形的左下角左边和右上角坐标,求这n个矩形的面积并 原题链接:http://acm.hdu.edu.cn/showproblem.php?pid=1542 典型的扫描线算法的题目 什么是 ...

  5. centos添加用户并赋予 root管理员权限

     centos添加用户并赋予 root管理员权限 用centos时,root用户一般都是超级管理员使用的,一般不轻易给别人,但是有时候同事安装软件时需要root账号,又不得不给,只能重新建一个用户,并 ...

  6. MySQL常用命令符

    收集于网络!!!! 解决字符乱码问题:显示汉语而非乱码:set names utf8: 修改新密码:update user set password=PASSWORD('新密码') where use ...

  7. linux-安装、启动nginx

    1.下载安装pcre库 pcre是一个正则表达式库,nginx的rewrite模块需要依赖该库. 下载地址:http://www.pcre.org/ wget https://ftp.pcre.org ...

  8. k线中转器

    自动同步服务器k线,将交易日k线存入共享内存,交易平台直接去共享内存取想要的数据. 默认提供期货1.3.5分钟.日线数据.如果想要自定义,可以通过copydata向它发送请求,可以提供任何周期,任何偏 ...

  9. 番外:克隆本地PDB中其他参数和子句的说明

    基于版本:19c (12.2.0.3) AskScuti 创建方法:克隆本地PDB(从本地其他PDB创建新的PDB) 对应路径:Creating a PDB --> Cloning --> ...

  10. 在多租户(容器)数据库中如何创建PDB:方法2 克隆本地PDB

    基于版本:19c (12.2.0.3) AskScuti 创建方法:克隆本地PDB(从本地其他PDB创建新的PDB) 对应路径:Creating a PDB --> Cloning --> ...