$\dfrac 2\pi$是个引人注目的数字,先来看看它到底是什么东西

假如有一条直线,它和题目所给的某条长度为$d$的线段夹角为$\theta$,那么线段在直线上的投影长度为$\left|d\cos\theta\right|$

现在我们随机一条直线,于是线段的期望投影长度是$\dfrac{\int_0^\pi\left|d\cos\theta\right|d\theta}{\pi-0}=\dfrac2\pi d$

所以我们可以不停随机一个角度,把所有线段投影到这个角度的直线上,一旦检查到总投影长度与原长之比$\geq\dfrac2\pi$就停止

找(?)到合适的角度之后,我们按线段端点投影在直线上的横坐标把所有点分成左右两部分,找一种连线方法使得每条线端的两个端点一个在左边一个在右边,且连线不相交,这样就做完了这道题

当然一些细节是不得不讲的

①随机?问题不大...期望都是$\dfrac2\pi$了,想随机到一个比它大的一点都不难(这也顺带说明了不存在无解的情况)

②设原来线段总长为$len$,原来投影总长为$d$,求得答案的投影总长为$d'$,求得答案的线段总长为$len'$,那么显然有$\dfrac2\pi len\leq d$和$d'\leq len'$

考虑比较$d$和$d'$,我们要求答案的所有线段的端点分列左右两边,对应过来就是投影线段穿越中轴线,如果原来存在两条投影线段不穿越中轴线,我们换一种方式连接即可满足要求,这样一来投影长度还增加了,所以$d\leq d'$

③怎么用合适的方法连线(不相交)

我们可以这样做:每次选取左半边的最左最下点,把其他点做极角排序,扫描的过程中统计扫描线下方左右两边的点数,一旦相同,连一条边并递归上下处理,这样就保证了连线不相交

实现的时候可以不用写成递归的形式,对于分开的上下两组,分别打上不同的标记即可,下次处理到这里只需要找标记相同的点,跟递归差不多的意思gr

然后就做完了,挺愉悦的==

#include<stdio.h>
#include<math.h>
#include<algorithm>
using namespace std;
const double pi=3.141592653589793238462643383;
struct point{
	double x,y;
	point(double a=0,double b=0){x=a;y=b;}
}p[10010],a[10010];
double dis(point a,point b){return sqrt((a.x-b.x)*(a.x-b.x)+(a.y-b.y)*(a.y-b.y));}
int match[10010],id[10010],s[10010],c[10010],bl[10010];
bool v[10010];
double ang[10010];
bool cmpx(int x,int y){return a[x].x<a[y].x||(a[x].x==a[y].x&&a[x].y<a[y].y);}
bool cmpa(int x,int y){return ang[x]<ang[y];}
int main(){
	int n,i,j,k,x,y,l,c0,c1,tot;
	double sum,tmp,d,dx,dy;
	scanf("%d",&n);
	for(i=1;i<=n<<1;i++)scanf("%lf%lf",&p[i].x,&p[i].y);
	sum=0;
	for(i=1;i<=n;i++){
		scanf("%d%d",&x,&y);
		sum+=dis(p[x],p[y]);
	}
	while(1){
		d=(rand()%10000)/10000.*2*pi;
		dx=cos(d);
		dy=sin(d);
		for(i=1;i<=n<<1;i++)a[i]=point(p[i].x*dx-p[i].y*dy,p[i].x*dy+p[i].y*dx);
		for(i=1;i<=n<<1;i++)id[i]=i;
		sort(id+1,id+(n<<1|1),cmpx);
		tmp=0;
		for(i=1;i<=n;i++)tmp+=a[id[i+n]].x-a[id[i]].x;
		if(tmp>=2/pi*sum)break;
	}
	for(i=1;i<=n;i++){
		s[id[i]]=0;
		s[id[i+n]]=1;
	}
	tot=0;
	for(i=1;i<=n;i++){
		x=id[i];
		v[x]=1;
		l=0;
		for(j=1;j<=n<<1;j++){
			if(!v[j]&&bl[j]==bl[x]){
				ang[j]=atan2(a[j].y-a[x].y,a[j].x-a[x].x);
				l++;
				c[l]=j;
			}
		}
		sort(c+1,c+l+1,cmpa);
		c0=c1=0;
		for(j=1;j<=l;j++){
			y=c[j];
			if(s[x]!=s[y]&&c0==c1){
				match[x]=y;
				match[y]=x;
				v[y]=1;
				tot++;
				for(k=1;k<j;k++)bl[c[k]]=tot;
				break;
			}
			if(s[y])
				c1++;
			else
				c0++;
		}
	}
	for(i=1;i<=n<<1;i++){
		if(match[i]>i)printf("%d %d\n",i,match[i]);
	}
}

[Contest20180321]nonintersect的更多相关文章

  1. 【XSY2760】nonintersect 计算几何

    题目描述 平面上有\(n\)条线段,你要擦掉所有线段但保留原有的\(2n\)个端点,然后连接这些端点形成\(n\)条不相交的线段,每个端点只能在一条线段中. 假设你画的线段总长为\(Y\),原有线段的 ...

  2. [算法]检测空间三角形相交算法(Devillers & Guigue算法)

    #pragma once //GYDevillersTriangle.h /* 快速检测空间三角形相交算法的代码实现(Devillers & Guigue算法) 博客原地址:http://bl ...

  3. Foundations of Machine Learning: The PAC Learning Framework(1)

    写在最前:本系列主要是在阅读 Mehryar Mohri 等的最新书籍<Foundations of Machine Learning>以及 Schapire 和 Freund 的 < ...

随机推荐

  1. spring事务不回滚 自己抛的异常

    在service代码中   throw new Excepion("自定义异常“) 发现没有回滚, 然后百度了下, 改为抛出运行时异常  throw new RuntimeException ...

  2. Ubuntu下安装LNMP之nginx的安装

    Nginx 最初是作为一个 Web 服务器创建的,用于解决 C10k 的问题.作为一个 Web 服务器,它可以以惊人的速度为您的数据服务.但 Nginx 不仅仅是一个 Web 服务器,你还可以将其用作 ...

  3. HDU 2639 01背包求第k大

    Bone Collector II Time Limit: 5000/2000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others ...

  4. React.js基础知识

    一. react.js的基本使用方法 (1)快速使用,hello world <div id="app"></div> <script src=&qu ...

  5. Nginx使用教程----提高Nginx网络吞吐量之buffers优化

    请求缓冲区在NGINX请求处理中起着重要作用. 在接收到请求时,NGINX将其写入这些缓冲区. 这些缓冲区中的数据可作为NGINX变量使用,例如$request_body. 如果缓冲区与请求大小相比较 ...

  6. LOJ tangjz的背包

    题目大意 有 \(n\) 个物品, 第 \(i\) 个物品的体积为 \(i\) 令 \(f(x)\) 为 选择 \(m\) 个物品, 体积和为 \(x\) 的方案数 令 \(V = \sum_{i=1 ...

  7. Spring - IoC(2): 属性注入 & 构造注入

    依赖注入是指程序运行过程中,如果需要另外的对象协作(访问它的属性或调用它的方法)时,无须在代码中创建被调用者,而是依赖于外部容器的注入. 属性注入(Setter Injection) 属性注入是指 I ...

  8. 【bzoj1911-[Apio2010]特别行动队】斜率优化

    [题目描述] 有n个数,分成连续的若干段,每段的分数为a*x^2+b*x+c(a,b,c是给出的常数),其中x为该段的各个数的和.求如何分才能使得各个段的分数的总和最大. [输入格式]  第1行:1个 ...

  9. 关于Javascript 闭包的理解

    一.什么是闭包? 官方”的解释是:闭包是一个拥有许多变量和绑定了这些变量的环境的表达式(通常是一个函数),因而这些变量也是该表达式的一部分.相信很少有人能直接看懂这句话,因为他描述的太学术.其实这句话 ...

  10. PHP正则经典漏洞

    @author: Dlive P牛在小密圈中发的一个有关使用PHP正则配合写配置文件导致Getshell的经典漏洞 漏洞代码是这样的: <?php //ph.php $str = addslas ...