HDU 6631 line symmetric 计算几何
题目链接: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 计算几何的更多相关文章
- HDU 6631 line symmetric(枚举)
首先能想到的是至少有一对相邻点或者中间间隔一个点的点对满足轴对称,那么接下来只需要枚举剩下的点对是否满足至多移动一个点可以满足要求. 第一种情况,对于所有点对都满足要求,那么Yes. 第二种情况,有一 ...
- HDU 5130 Signal Interference(计算几何 + 模板)
HDU 5130 Signal Interference(计算几何 + 模板) 题目链接http://acm.hdu.edu.cn/showproblem.php?pid=5130 Descripti ...
- HDU 3400 Line belt (三分再三分)
HDU 3400 Line belt (三分再三分) ACM 题目地址: pid=3400" target="_blank" style="color:rgb ...
- 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 ...
- HDU 5979 Convex【计算几何】 (2016ACM/ICPC亚洲区大连站)
Convex Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65536/65536 K (Java/Others)Total Subm ...
- 三分套三分 --- HDU 3400 Line belt
Line belt Problem's Link: http://acm.hdu.edu.cn/showproblem.php?pid=3400 Mean: 给出两条平行的线段AB, CD,然后一 ...
- HDU 4606 Occupy Cities (计算几何+最短路+最小路径覆盖)
转载请注明出处,谢谢http://blog.csdn.net/ACM_cxlove?viewmode=contents by---cxlove 题目:给出n个城市需要去占领,有m条线段是障碍物, ...
- 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 ...
- HDU 5839 Special Tetrahedron 计算几何
Special Tetrahedron 题目连接: http://acm.hdu.edu.cn/showproblem.php?pid=5839 Description Given n points ...
随机推荐
- JDBC用户访问被拒绝
线程“主”java中的异常.于sq1.sQLException:用户“root”@“localhost”被拒绝访问(使用密码:YES)root密码错误
- Linux监控工具nmon
Linux监控工具 nmon nmon是一种在Linux操作系统上广泛使用的监控与分析工具,nmon所记录的信息是比较全面的,它能在系统运行 过程中实时地捕捉系统资源的使用情况,并且能输出结果到文件中 ...
- java连接mysql数据库8.0以上版本过程中遇到的坑
来自:https://blog.csdn.net/u013276277/article/details/80255468 首先,我居然不能用navicat客户端连接上mysql8.0数据库报1251错 ...
- 【译】写个好的 CLI 程序
写个好的 CLI 程序 Write a Good CLI Program 译文 原文链接:https://qiita.com/tigercosmos/items/678f39b1209e60843cc ...
- ajax post
前端 $.post("url",JSON.stringify({ a:a, ... }), function(data){ }, 'json'); 后端 @PostMapping( ...
- Docker 进入正在运行的容器的4种方式
在使用Docker创建了容器之后,如何进入该容器呢? 进入Docker容器比较常见的几种做法如下: 使用docker attach 使用SSH 使用nsenter 使用exec 一.使用docker ...
- angular 读写电脑本地文件
angular 读写本地电脑文件 angular将数据写进到电脑文件 在前端写一个按钮,然后点击按钮的时候在本地电脑保存一个text文件. 这时候我们需要用到一个angular的插件,叫做" ...
- SpringBoot整合Mybatis案例
SpringBoot整合Mybatis案例 2019/7/15以实习生身份入职公司前端做Angular ,但是感觉前途迷茫,于是乎学习一下Java的框架——SpringBooot. 参照大神博客:ht ...
- schroeder reverb matlab实现
原理参考:Natural sounding artificial reverberation combFilter.m: function output = combFilter(delay, gai ...
- [Note]后缀自动机
后缀自动机 代码 #include <cstdio> #include <algorithm> #include <cstring> const int M = 1 ...