SGU 128. Snake --- 暴力枚举+并查集+贪心+计算几何
128. Snake
time limit per test: 0.25 sec.
memory limit per test: 4096 KB
There are N points given by their coordinates on a plane. All coordinates (xi,yi) are integers in a range from -10000 up to 10000 inclusive . It is necessary to construct a broken line satisfying the following conditions:
1. The broken line should be closed.
2. End points of each segment (verteces) of the broken line can only be the given points, and all given points should be used.
3. Each two consecutive segments of the broken line should form a corner of 90 degrees in each vertex point.
4. The sides of the broken line should be parallel to coordinate axes.
5. The broken line should have no self-crossing and self-contact.
6. The broken line should have the minimal length.
You have to either find the length L of the constructed broken line, or determine that it is impossible to construct such a broken line.
Input
First line contains the number N (4 <= N <= 10000) - amount of points. Each of the following N lines contains coordinates of points separated by space xi and yi (1 <= i <= N). Points are given in random order.
Output
First line should contain the length of the broken line L or 0 if there is no solution.
Sample Input
Sample Output
4 0 0 0 3 3 3 3 0
Sample Output
12
【题目大意】
在一个平面坐标中有N个点,现在要你用这N个点构造一个闭合图形,这个图形要满足以下条件:
1.这个图形要是闭合的;
2.图形上的点只能是给定的点,且每个点只能用一次;
3.每个顶点相连的两条边必须互相垂直;
4.每条边都要平行于坐标轴;
5.每条线除了顶点外都不能互相相交;
6.闭合图形的周长要最小;
N-----点的个数
接下来N个点。
如果存在则输出最小长度;否则输出0。
题目意思很easy,但是实现的时候要考虑很多小细节,和队友两个人讨论了一天,感觉代码实现的能力还是短板,需要加强。
【题目分析】
1.首先,点的个数必须是偶数,这样才能满足每个点相连的两条边都是90度的条件;
2. 同一个x值或同一个y值只能对应偶数个坐标;
3.对于像a(x1,y),b(x2,y),c(x3,y),d(x4,y)类型的,只能是跳跃的连接,即:a-b,c-d;
4.根据题给的前四个条件,可以知道这个多边形一定是唯一的,所以就省去了找最有多边形的麻烦;
接下来就是判断是否能够用所有点来实现一个闭合曲线的问题了:
1.只能有一个连通分支;------------------------并查集or深搜
2.不能出现两边相交(除给定的点外)-------------暴力or线段树
对于判断连通分支的话肯定是并查集好一点,一开始我用dfs做了,感觉建图就卡了老半天。
2.判断是否相交的情况:线段树当然是首选,但是这题暴力也能60ms水过,我就不说什么了。
一开始代码写残了,分析了各种图形,什么“回”字形,“T”字形,“8”字形分析了一大堆,代码各种打补丁。最后还是得全部删了重写。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 | //Memory Time // 1726K 63MS #include<algorithm> #include<cstdio> #include<cstring> #include<cstdlib> #include<iostream> #include<vector> #include<queue> #include<stack> #include<iomanip> #include<string> #include<cmath> #include<bits/stdc++.h> #define LL __int64 #define MAX 10010 #define exit {puts("0"); return 0;} using namespace std; int N; int father[MAX]; int Hx,Sx; struct Node { int x,y,id; }; Node node[MAX]; struct edge { Node s,e; }; edge hx[3*MAX],sx[3*MAX]; void read() { cin>>N; for ( int i=1;i<=N;i++) { cin>>node[i].x>>node[i].y; node[i].id=i; father[i]=i; } } bool cmp1(Node a,Node b) { if (a.y==b.y) return a.x<b.x; else return a.y<b.y; } bool cmp2(Node a,Node b) { if (a.x==b.x) return a.y<b.y; else return a.x<b.x; } int find( int x) { return father[x] == x ? x : father[x] = find(father[x]); } bool build_hx_edge() { sort(node+1,node+1+N,cmp2); for ( int i=1;i<N;i+=2) { if ((node[i].x!=node[i+1].x)||(node[i].y==node[i+1].y)) return 0; hx[Hx].s=node[i]; hx[Hx].e=node[i+1]; Hx++; int x=find(node[i].id); int y=find(node[i+1].id); if (x!=y) father[x]=y; } return 1; } bool build_sx_edge() { sort(node+1,node+1+N,cmp1); for ( int i=1;i<N;i+=2) { if ((node[i].y!=node[i+1].y)||(node[i].x==node[i+1].x)) return 0; sx[Sx].s=node[i]; sx[Sx].e=node[i+1]; Sx++; int x=find(node[i].id); int y=find(node[i+1].id); if (x!=y) father[x]=y; } return 1; } bool Is_connect() { int tp=find(1); for ( int i=2;i<=N;i++) if (find(i)!=tp) return 0; return 1; } bool judge() { for ( int i=0;i<Hx;i++) for ( int j=0;j<Sx;j++) if (sx[j].s.x < hx[i].s.x && hx[i].s.x < sx[j].e.x&& hx[i].s.y < sx[j].s.y && sx[j].s.y < hx[i].e.y) return 0; return 1; } int calcu() { int ans=0; for ( int i=0;i<Hx;i++) ans+=hx[i].e.y-hx[i].s.y; for ( int i=0;i<Sx;i++) ans+=sx[i].e.x-sx[i].s.x; return ans; } int main() { // freopen("cin.txt","r",stdin); // freopen("cout.txt","w",stdout); read(); if (N==0) exit if (!build_hx_edge()) //构造横边 exit if (!build_sx_edge()) //构造竖边 exit if (!Is_connect()) exit if (!judge()) exit cout<<calcu()<<endl; return 0; } |
作者:北岛知寒
出处:https://www.cnblogs.com/crazyacking/p/3825549.html
版权:本作品采用「署名-非商业性使用-相同方式共享 4.0 国际」许可协议进行许可。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 如何编写易于单元测试的代码
· 10年+ .NET Coder 心语,封装的思维:从隐藏、稳定开始理解其本质意义
· .NET Core 中如何实现缓存的预热?
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
· AI与.NET技术实操系列:向量存储与相似性搜索在 .NET 中的实现
· 周边上新:园子的第一款马克杯温暖上架
· Open-Sora 2.0 重磅开源!
· 分享 3 个 .NET 开源的文件压缩处理库,助力快速实现文件压缩解压功能!
· Ollama——大语言模型本地部署的极速利器
· DeepSeek如何颠覆传统软件测试?测试工程师会被淘汰吗?