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的更多相关文章
随机推荐
- zoj 3822 Domination (可能性DP)
Domination Time Limit: 8 Seconds Memory Limit: 131072 KB Special Judge Edward is the headm ...
- 一些Android框架
从网上收集一些框架,敲代码偷懒这些框架非常实用,必须记下来,为了以后少写代码,用别人好的框架 ThinkAndroid ThinkAndroid(一个ThinkAndroid教程地址:http://m ...
- MVC区域 vs2013 mvc 搭建基架项
http://www.it165.net/pro/html/201404/12822.html
- android实现应用程序仅仅有在第一次启动时显示引导界面
概述 SharedPreferences的使用很easy,可以轻松的存放数据和读取数据.SharedPreferences仅仅能保存简单类型的数据,比如,String.int等.通常会将复杂类型的数据 ...
- 如何设置多个同一页的tinymce编辑
的页面设置多个tinymce编辑器 This example shows how to setup multiple editors on the same page and with differe ...
- Android 高仿微信即时聊天 百度云为基础的推
转载请注明出处:http://blog.csdn.net/lmj623565791/article/details/38799363 ,本文出自:[张鸿洋的博客] 一直在仿微信界面,今天最终有幸利用百 ...
- acdream 1211 Reactor Cooling 【边界网络流量 + 输出流量】
称号:acdream 1211 Reactor Cooling 分类:无汇的有上下界网络流. 题意: 给n个点.及m根pipe,每根pipe用来流躺液体的.单向的.每时每刻每根pipe流进来的物质要等 ...
- simpleDateFormat日期格式转换
1------------------------------------------------------------------------------------- package com.n ...
- top 查看资源使用
top:动态观察程序的变化 ? [root@linux ~]# top [-d] | top [-bnp] 参数: -d :后面可以接秒数,就是整个程序画面更新的秒数.预设是 5 秒: -b :以批次 ...
- spring来源理解-BeanFactory子类XmlBeanFactory创建过程
BeanFactory 1:BeanFactory什么: 官方解释The root interface for accessing a Spring bean container,翻译成中文sprin ...