题目链接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. springboot整合websocket实现客户端与服务端通信

    定义  WebSocket是通过单个TCP连接提供全双工(双向通信)通信信道的计算机通信协议.此WebSocket API可在用户的浏览器和服务器之间进行双向通信.用户可以向服务器发送消息并接收事件驱 ...

  2. (四)tensorflow-基础(数据类型,张量操作,数学运算)

    摘要: 1.数据类型:标量.向量.矩阵.张量  :数值精度:变量(张量) 2.张量操作:索引.切片.维度操作 3.数学运算:加减乘除(整除和余除):乘方(平方.开方.指数):自然底对数(任意底对数需要 ...

  3. [0CTF 2016]piapiapia{PHP反序列化漏洞(PHP对象注入)}

    先上学习链接: https://www.freebuf.com/column/202607.html https://www.cnblogs.com/ichunqiu/p/10484832.html ...

  4. c++踩坑大法好 赋值和指针的区别

    1,先说结论: 两个指针指向同一个结构,一个改了结构,另一个也会改掉. 两个指针指向同一个结构,修改了其中一个的指向,并且改了其中的内容,另一个不为所动. 2,看例子 main.cpp #includ ...

  5. opencv3.2.0+opencv_contrib-3.2.0+vs2015开发配置

    在sift算法实现中,出现了这个问题 出现问题:\vs2015opencv\vs2015\project\mode\mode\sift算法1.cpp(3): fatal error C1083: 无法 ...

  6. 快速ni

    代码: while(p>0)                   (mul(a,b)) = a*b; { 等同于二分 if(p%2==1) mul(ans,a); 目的是为了二分个基数的二次方乘 ...

  7. 切换目录命令 - cd

    1) 命令名称:cd 2) 英文原意:change directory 3) 命令所在路径:shell 内置命令 4) 执行权限:所有用户 5) 功能描述:切换目录 6) 语法: cd[目录名] 例子 ...

  8. IN中超过1000处理

    后台 所有用到IN的方法,都要考虑超过1000的可能 if(cameraIds != null && cameraIds.length > 0){sql.append(" ...

  9. cookie 与 session区别

    cookie 与 session 是网页开发中常用的信息存储方式.Cookie是在客户端开辟的一块可存储用户信息的地方:Session是在服务器内存中开辟的一块存储用户信息的地方.JavaScript ...

  10. JQuery-Snowfall降雪插件使用

        一个很好使用的降雪插件,可以实现雪花.爱心.图片等下降落. 1.JQuery-Snowfall插件的使用方法: 增加了使用图像作为雪花而不是纯色元素的功能. $(element).snowfa ...