sgu128snack
按我的理解大概说下题意:
有非常多个点,最多一万个,告诉你它们的坐标。如今须要构造一条闭合线。这个闭合线满足下面六点:
1必须是闭合的。
2必须用到全部的点。
3构造的线段之间若成角,则必须是90度。
4构造的边必须与x或y轴平行。
5构造的线段之间不存在交错和反复的情况。
6最后形成的闭合线长度必需要是全部可能中最短的。
由于我认为能不用复杂的数据结构就不用,能不写麻烦的算法就不写,所以估算了一下时间复杂度,发现能够
用暴力,于是,我的做法就是暴力。
以下是较具体的做法:
既然要构造一条线出来,直接构造的话,我不知道怎么搞,于是用分治的思想,每次弄两个点出来,看应不应该
把它们连起来,因为要求成角必须是90,又要线的长度最短,于是当两个点的横坐标或纵坐标相等,它们之间的
距离与它们之中随意一点跟它们之外的其他点的距离相比是最短的话,那么就能够相连。
实现这个过程,我是用两次排序排序,第一次排序,假设横坐标不等则按横坐标递增排序,否则按纵坐标递增排序,
第1个点跟第2个点相连,第3个点跟第4个点相连,以此类推。第二次排序,假设纵坐标不等则按纵坐标递增排序,
否则按横坐标递增排序,相同的,第1个点跟第2个点相连,第3个点跟第4个点相连,以此类推。
这样就把全部的点给连好了。
当然这种话,结果不一定是一个闭合的线,可能有多个闭合线,当然也有可能没有闭合的线,或是有两条线段交错的情况。
所以还须要推断是否闭合以及唯一,也就是说,推断构造出的线段能否形成一个连通图,这个用并查集就好。
也要推断是否有两条线段交错,这个的话,我直接枚举全部情况,我把横线跟竖线分开,然后枚举是否有横线跟竖线交错,
假设构造的图连通,那么最多有一万条边,横线跟竖线的数量也是一样多的,也就是最多各位五千,那么枚举的数量是
五千的平方,也就是25乘以10的6次方,题目给了250ms,所以时间上绰绰有余,不会超时。
于是推断之后,假设发现图是一个连通图,又没有线段交错的情况,那么就能够把构造好的闭合线长度输出来了。
我AC的代码例如以下:
#include<iostream>
#include<cstring>
#include<algorithm>
#include<map>
using namespace std;
#define end {printf("0");return 0;}
int num_dot,num_x,num_y,father[10001];
struct node
{
int x,y,no;
}dot[10001];
struct node1
{
node s,e;
}sidex[10001],sidey[10001];
int sf(int i)
{
while(i!=father[i])
i=father[i];
return i;
}
bool isconnex()
{
int i,a,b,sum=0;
for(i=0;i<num_dot;i++)
father[i]=i;
for(i=0;i<num_x;i++)
father[sf(sidex[i].s.no)]=sf(sidex[i].e.no);
for(i=0;i<num_y;i++)
father[sf(sidey[i].s.no)]=sf(sidey[i].e.no);
for(i=0;i<num_dot;i++)
if(father[i]==i)
{
sum++;
if(sum>1)
return 0;
}
return 1;
}
bool cmp1(node a,node b)
{
if(a.x!=b.x)
return a.x<b.x;
return a.y<b.y;
}
bool cmp2(node a,node b)
{
if(a.y!=b.y)
return a.y<b.y;
return a.x<b.x;
}
int newside()
{
int i,sum=0;
num_x=num_y=0;
sort(dot,dot+num_dot,cmp1);
for(i=0;i<num_dot;i+=2)
if(dot[i].x!=dot[i+1].x)
return -1;
else
{
sum+=dot[i+1].y-dot[i].y;
sidex[num_x].s=dot[i];
sidex[num_x].e=dot[i+1];
num_x++;
}
sort(dot,dot+num_dot,cmp2);
for(i=0;i<num_dot;i+=2)
if(dot[i].y!=dot[i+1].y)
return -1;
else
{
sum+=dot[i+1].x-dot[i].x;
sidey[num_y].s=dot[i];
sidey[num_y].e=dot[i+1];
num_y++;
}
return sum;
}
bool iscross()
{
int i,j;
for(i=0;i<num_x;i++)
for(j=0;j<num_y;j++)
if(sidex[i].s.x>sidey[j].s.x&&sidex[i].s.x<sidey[j].e.x&&sidey[j].s.y>sidex[i].s.y&&sidey[j].s.y<sidex[i].e.y)
return 1;
return 0;
}
int main()
{
int i,sum;
scanf("%d",&num_dot);
for(i=0;i<num_dot;i++)
{
scanf("%d%d",&dot[i].x,&dot[i].y);
dot[i].no=i;
}
if(num_dot&1)
end
sum=newside();
if(sum==-1)
end
if(isconnex()&&!iscross())
printf("%lld",sum);
else
end
}
sgu128snack的更多相关文章
随机推荐
- bootstrap jQuery Ztree异步载入数据,check选择&可加入、改动、删除节点
效果图: 一.下载zTree插件 地址:http://www.ztree.me 二.html代码 <link href="../Scripts/zTree/css/zTreeStyle ...
- async和await用法
原文:async和await用法 要理解async和await的用法,首先要了解Task相关知识,这里不做说明,因为这不是本文的重点. 如果你已经对Task很了解,那么如何使用async和await, ...
- HttpURLConnection请求数据流的写入(write)和读取(read)
URLConnection类给应用 程序 和web资源之间架设起了通信的桥梁,这些web资源通常是通过url来标记的,本文将讲述如何使用HttpURLConnection来访问web页面(发送数据流) ...
- Redis安装及简单測试
摘要: Redis是眼下业界很受到欢迎的一个内存数据库,一般用作系统的中间缓存系统,用以提升总体商业系统的吞吐量和响应速度.本文将简要介绍安装的主要过程以及给出一个简要的測试代码. 1. 系统环境和 ...
- hdu 4107当卡段树
其核心思想是记录最大的节点值和最低值,假设max<p要么min>=p时间,在节点只变化add值,不要子树遍历:否则,就往子树递归. #include<iostream> #in ...
- 构造Nexus,仓库部署成员Nexus仓
在一个,我们描述了如何配置安装nexus制,本节,我们来介绍nexus采用 1.登录 在红色的部分点击登陆.输入username与password admin/admin123. 这里能够配置nexu ...
- Android 之流媒体播放器,广播侧下方这么简单。
没有其他的.希望从事流媒体开发案例.还承诺提供朋友博客.上个星期.制定出最后一点机会. 在这里,与大家分享. 首先要明白的概念:什么是流媒体?转载请注明出处http://blog.csdn.net/g ...
- hdu 5073 Galaxy(2014acm鞍山亚洲分部 C)
主题链接:http://acm.hdu.edu.cn/showproblem.php? pid=5073 Galaxy Time Limit: 2000/1000 MS (Java/Others) ...
- 通过action 跨进程启动activity
在一些场景中我们需要从一个进程启动另外的一个应用的activity,这有什么好办法? 这里介绍一种方法,通过自定义 action 通过filter来启动. 如果你需要启动一个你自己写的另一个app的a ...
- 【PHP】PHP5.4.0版本号ChangeLog具体解释(上)
前言 随着大量的框架使用composer和namespace,渐渐的线上环境也从之前的5.3变成了5.4或者5.5甚至5.6,随着7月份PHP7的公布,会有很多其它的公司採用新版本号. 之前好久就想写 ...