题目链接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. hackme.inndy.tw的一些Writeup(5月30更新)

    hackme.inndy.tw的一些Writeup(6月3日更新) 原文链接:http://www.cnblogs.com/WangAoBo/p/7706719.html 推荐一下https://ha ...

  2. 打开UML类图的正确姿势

    UML(Unified Modeling Language) 统一建模语言,又称标准建模语言.是用来对软件密集系统进行可视化建模的一种语言.UML的定义包括UML语义和UML表示法两个元素.UML是在 ...

  3. Mysql单实例数据库安装

    第1章 MySQL数据库安装 在当今的大中型互联网企业里,MySQL数据库服务几乎都是运行在Linux系列操作系统上,当然,你在可以运行在Windows/Unix等商业操作系统上,大中型互联网企业使用 ...

  4. Gogs的Docker容器化部署流程遇到的问题

    Gogs的Docker容器化部署流程遇到的问题   最近在学习CI/CD的一些方案,个人比较青睐容器化轻量级.CI方面一开始是想使用gitlab的,但是发现我自己买的服务器配置太低,内存根本不够(大写 ...

  5. 题解【AcWing176】装满的油箱

    题面 一开始拿到这个问题并不好做,于是考虑拆点. 考虑将一个点拆成 \(c+1\) 个,每个点表示(编号,剩余油量). 然后 \(\text{Dijkstra}\) 最短路即可. 每次跑 \(\tex ...

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

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

  7. IntelliJ IDEA 2017.3尚硅谷-----生成 javadoc

    Locale:输入语言类型:zh_CN Other command line arguments:-encoding UTF-8 -charset UTF-8

  8. 2. 移动端测试工具 :bugtags

    http://blog.csdn.net/objectivepla/article/details/51037804   Bugtags 使用说明 https://www.bugtags.com/   ...

  9. 进程管理 supervisor

    背景知识: supervisor是用Python开发的一套通用的进程管理程序,能将一个普通的命令行进程变为后台daemon,并监控进程状态,异常退出时能自动重启. 它是通过fork/exec的方式把这 ...

  10. 关于MySQL的tinyint(3)问题

    mysql 中int(1)和tinyint(1)中的1只是指定显示长度,并不表示存储长度.tinyint可以存储1字节, 即unsigned 0~255(signed -127~127).显示大小不受 ...