Codeforces 1045E. Ancient civilizations 构造 计算几何 凸包
原文链接https://www.cnblogs.com/zhouzhendong/p/CF1045E.html
4K码量构造题,CF血腥残暴!
题解
首先,如果所有点颜色相同,那么直接连个菊花搞定。
然后我们建个凸包。
如果凸包上有大于2段颜色(就是至少四段),比如这样
那么必然无解。
否则就只有一段颜色或者两段颜色:
这里我们先不管这个,考虑一个三角形的构造。
考虑三角形三个顶点颜色不全相同的情况,例如:
(两个白点的情况是等价的)
假如三角形区域内没有白点,那么直接全部连到其中一个黑点就好了。
否则假设里面有一个白点:
那么我们将白顶点连上这个中间的白点(将红色边加入最终答案),把原三角形划分成3个子问题递归求解即可。
回到原问题:
如果凸包上只有一种颜色,那么在里面找一个白点(因为已经排除全部都是黑点的情况了,所以必然有白点),如下图一样将红色边相连,按照红/黑色边将凸包三角划分成子问题解决即可:
如果凸包上有两种颜色,那么就类似地:
划分集合的暴力枚举点判定是否在三角形内就好了。
代码
#include <bits/stdc++.h>
#define clr(x) memset(x,0,sizeof (x))
using namespace std;
typedef long long LL;
LL read(){
LL x=0,f=0;
char ch=getchar();
while (!isdigit(ch))
f|=ch=='-',ch=getchar();
while (isdigit(ch))
x=(x<<1)+(x<<3)+(ch^48),ch=getchar();
return f?-x:x;
}
const int N=1005;
int n;
struct Point{
int x,y;
Point(){}
Point(int _x,int _y){
x=_x,y=_y;
}
friend Point operator + (Point A,Point B){
return Point(A.x+B.x,A.y+B.y);
}
friend Point operator - (Point A,Point B){
return Point(A.x-B.x,A.y-B.y);
}
friend bool operator == (Point A,Point B){
return A.x==B.x&&A.y==B.y;
}
friend bool operator != (Point A,Point B){
return A.x!=B.x||A.y!=B.y;
}
}O;
int cross(Point A,Point B){
return A.x*B.y-B.x*A.y;
}
int cross(Point A,Point B,Point C){
return cross(B-A,C-A);
}
int Dot(Point A,Point B){
return A.x*B.x+A.y*B.y;
}
int Dis(Point A,Point B){
return Dot(A-B,A-B);
}
struct civ{
Point p;
int c,id;
civ(){}
civ(Point _p,int _c,int _id){
p=_p,c=_c,id=_id;
}
};
civ Get_civ(int id){
Point p;
p.x=read(),p.y=read();
int c=read();
return civ(p,c,id);
}
vector <civ> p,con;
bool cmpO(Point a,Point b){
return a.y!=b.y?a.y<b.y:a.x<b.x;
}
bool cmpAngle_civ(civ a,civ b){
int c=cross(O,a.p,b.p);
return c?c>0:Dis(O,a.p)<Dis(O,b.p);
}
vector <civ> Get_Convex(vector <civ> p){
vector <civ> st(0);
int n=p.size();
for (int i=1;i<n;i++)
if (!cmpO(p[0].p,p[i].p))
swap(p[0],p[i]);
O=p[0].p;
sort(p.begin()+1,p.end(),cmpAngle_civ);
for (int i=0;i<n;i++){
while (st.size()>1&&cross(st[st.size()-2].p,st.back().p,p[i].p)<=0)
st.pop_back();
st.push_back(p[i]);
}
return st;
}
int check_same(){
for (int i=1;i<n;i++)
if (p[i].c!=p[0].c)
return 0;
return 1;
}
int check_inside(Point A,Point B,Point C,Point P){
if (P==A||P==B||P==C)
return 0;
int S1=abs(cross(A,B,C));
int S2=abs(cross(P,A,B))+abs(cross(P,B,C))+abs(cross(P,C,A));
return S1==S2;
}
vector <civ> get_inside(Point A,Point B,Point C,vector <civ> S){
static vector <civ> res;
res.clear();
for (auto v : S)
if (check_inside(A,B,C,v.p))
res.push_back(v);
return res;
}
vector <pair <int,int> > ans;
void solve(civ A,civ B,civ C,vector <civ> S){
int flag=0;
civ p;
for (auto c : S)
if (c.c!=A.c){
flag=1,p=c;
break;
}
if (!flag){
for (auto c : S)
ans.push_back(make_pair(A.id,c.id));
return;
}
ans.push_back(make_pair(C.id,p.id));
solve(A,B,p,get_inside(A.p,B.p,p.p,S));
solve(C,p,A,get_inside(C.p,p.p,A.p,S));
solve(C,p,B,get_inside(C.p,p.p,B.p,S));
}
int main(){
n=read();
for (int i=1;i<=n;i++)
p.push_back(Get_civ(i));
con=Get_Convex(p);
int cnt=con[0].c^con.back().c;
for (int i=1;i<con.size();i++)
cnt+=con[i-1].c^con[i].c;
if (cnt>2)
return puts("Impossible"),0;
ans.clear();
if (cnt==0){
if (check_same()){
printf("%d\n",n-1);
for (int i=1;i<n;i++)
printf("%d %d\n",0,i);
return 0;
}
for (int i=1;i<con.size();i++)
ans.push_back(make_pair(con[i-1].id,con[i].id));
civ mid;
for (auto c : p)
if (c.c!=con[0].c){
mid=c;
break;
}
solve(con[0],con.back(),mid,get_inside(con[0].p,con.back().p,mid.p,p));
for (int i=1;i<con.size();i++)
solve(con[i-1],con[i],mid,get_inside(con[i-1].p,con[i].p,mid.p,p));
}
else {
vector <civ> _con(0);
int stco=con[0].c^1,i;
int m=con.size();
for (i=0;;i=(i+1)%m)
if (con[i].c==stco){
_con.push_back(con[i]);
if (con[(i+1)%m].c!=stco)
break;
}
stco^=1;
for (i=(i+1)%m;;i=(i+1)%m)
if (con[i].c==stco){
_con.push_back(con[i]);
if (con[(i+1)%m].c!=stco)
break;
}
con=_con;
for (i=0;i<m;i++)
if (con[i].c!=con[(i+1)%m].c)
break;
int b=i;
for (int i=0;i<b;i++)
ans.push_back(make_pair(con[i].id,con[i+1].id));
for (int i=b+1;i<m-1;i++)
ans.push_back(make_pair(con[i].id,con[i+1].id));
b++;
for (int i=0;i<b-1;i++)
solve(con[i],con[i+1],con[b],get_inside(con[i].p,con[i+1].p,con[b].p,p));
for (int i=b;i<m-1;i++)
solve(con[i],con[i+1],con[0],get_inside(con[i].p,con[i+1].p,con[0].p,p));
}
printf("%d\n",(int)ans.size());
for (auto e : ans)
printf("%d %d\n",e.first-1,e.second-1);
return 0;
}
Codeforces 1045E. Ancient civilizations 构造 计算几何 凸包的更多相关文章
- Codeforces Beta Round #1 C. Ancient Berland Circus 计算几何
C. Ancient Berland Circus 题目连接: http://www.codeforces.com/contest/1/problem/C Description Nowadays a ...
- Codeforces Gym100543B 计算几何 凸包 线段树 二分/三分 卡常
原文链接https://www.cnblogs.com/zhouzhendong/p/CF-Gym100543B.html 题目传送门 - CF-Gym100543B 题意 给定一个折线图,对于每一条 ...
- 计算几何---凸包问题(Graham/Andrew Scan )
概念 凸包(Convex Hull)是一个计算几何(图形学)中的概念.用不严谨的话来讲,给定二维平面上的点集,凸包就是将最外层的点连接起来构成的凸多边型,它能包含点集中所有点的.严谨的定义和相关概念参 ...
- 计算几何-凸包-toleft test
toLeftTest toLeftTest是判断一个点是否在有向直线左侧的算法. 当点s位于向量pq左侧时,toLeftTest返回true.当点s位于向量pq右侧时,toLeftTest返回fals ...
- 计算几何-凸包算法 Python实现与Matlab动画演示
凸包算法是计算几何中的最经典问题之一了.给定一个点集,计算其凸包.凸包是什么就不罗嗦了 本文给出了<计算几何——算法与应用>中一书所列凸包算法的Python实现和Matlab实现,并给出了 ...
- Codeforces 1383D - Rearrange(构造)
Codeforces 题面传送门 & 洛谷题面传送门 一道不算困难的构造,花了一节英语课把它搞出来了,题解简单写写吧( 考虑从大往小加数,显然第三个条件可以被翻译为,每次加入一个元素,如果它所 ...
- Codeforces 549B. Looksery Party[构造]
B. Looksery Party time limit per test 1 second memory limit per test 256 megabytes input standard in ...
- 【BZOJ-1069】最大土地面积 计算几何 + 凸包 + 旋转卡壳
1069: [SCOI2007]最大土地面积 Time Limit: 1 Sec Memory Limit: 128 MBSubmit: 2707 Solved: 1053[Submit][Sta ...
- codeforces 323A. Black-and-White Cube 构造
输入n 1 <= n <= 100 有一个n * n * n 的立方体,由n ^ 3 个1 * 1 * 1 的单位立方体构成 要用white 和 black 2种颜色来染这n ^ 3个立方 ...
随机推荐
- Qt QWidget
原文: https://www.cnblogs.com/muyuhu/archive/2012/10/26/2741184.html QWidget 类代表一般的窗口,其他窗口类都是从 QWidget ...
- 2.3 os 模块
目录 2.3.1 功能 2.3.2 常用方法 2.3.2.1 创建相关 2.3.2.2 切换相关 2.3.2.3 查看相关 2.3.2.4 编辑相关 2.3.2.5 删除相关 2.3.1 功能 2.3 ...
- JVM运行时内存组成分为一些线程私
JVM运行时内存组成分为一些线程私有的,其他的是线程共享的. 线程私有 程序计数器:当前线程所执行的字节码的行号指示器. Java虚拟机栈:java方法执行的内存模型,每个方法被执行时都会创建一个栈帧 ...
- emwin 之 LISTWVIEW 控件禁止列滑动
@2019-02-25 [小记] hHeader = LISTVIEW_GetHeader(hListView); WM_DisableWindow(hHeader);
- linux18.04+jdk11.0.2+hadoop3.1.2部署伪分布式
1. 下载 安装hadoop3.1.2http://mirror.bit.edu.cn/apache/hadoop/common/hadoop-3.1.2/hadoop-3.1.2.tar.gz 注意 ...
- <% String path = request.getContextPath(); String basePath = request.getScheme()+"://"+request.getServerName()+":"+request.getServerPort()+path+"/"; %>
<%String path = request.getContextPath();String basePath = request.getScheme()+"://"+re ...
- 一个select元素自定义设计的新思路:appearance: none之后利用<>符号制造小箭头
最近工作时解决了一个前端小问题(如下图所示):在Safari中,select的控件之上有不和谐的灰色部分. 刚开始时我以为是backgrand或是border设置不当之类产生的问题,在搜索了很久之后终 ...
- TCP和UDP
目录: TCP流式协议 TCP模板 TCP聊天室 TCP通信与连接循环 TCP粘包 socketserver实现并发 UDP数据报协议 UDP模板 UDP传输 socketserver实现并发 TCP ...
- 高并发秒杀系统--Service事务管理与继承测试
[Spring IoC的类型及应用场景] [Spring事务使用方式] [Spring事务的特性] [Spring事务回滚的理解] [Service声明式事务的配置] 1.配置事务管理器 2.配置基 ...
- go语言学习 一
1.变量声明 指定变量类型,声明后若不赋值,使用默认值 根据值自行判定变量类型. 省略var, 注意 :=左侧的变量不应该是已经声明过的,否则会导致编译错误 2.go语言作用域 函数内定义的变量称为局 ...