SGU 128.Snake

时间限制:0.25s

空间限制:4m

题意:

在一个平面坐标中有N个点,现在要你用这N个点构造一个闭合图形,这个图形要满足以下条件:

1.这个图形要是闭合的;
         2.图形上的点只能是给定的点,且每个点只能用一次;
         3.每个顶点相连的两条边必须互相垂直;
         4.每条边都要平行于坐标轴;
         5.每条线除了顶点外都不能互相相交;
         6.闭合图形的周长要最小;

N-----点的个数
         接下来N个点。
         如果存在则输出最小长度;否则输出0。



Solution:

重点在所求图形所有的边都是平行于X轴或Y轴,那么要使所有点成直角,只要对所有点先对X轴再对Y轴排序

很容易发现对于在同一条竖线方向和同一条横线方向的点,一定是两个两个点相连。

现在问题是如何判断线段相交的情况

假如现在已经连接完所有竖直方向的边,接着我们连接横向的边,两点为(x1,y,x2,y),

如果存在一条竖直边(a,b1,a,b2)    使得x1<x<x2 且  b1<y<b2 那么这两条边相交

于是可以将排完序的所有的相同的x分为一组,如果x1,和x2所在的组内还有别的组的话即使得x1<x<x2 ,

就将那些组的边取出来,再判断 是否 b1<y<b2 是否满足,最后再判断得的的是否是只有一个闭合曲线,并查集即可。

参考代码:

#include <cstdio>
#include <iostream>
#include <algorithm>
using namespace std;
const int INF = 11111;
struct node {
	int x, y, Pxy, Pyx;
};
int f[INF];
node Axy[INF], Ayx[INF];
int pos[INF << 2], head[INF];
int n, x, y, ans;
int Find (int x) {
	if (f[x] != x) return f[x] = Find (f[x]);
	return x;
}
void getT (int a, int b) {
	f[Find (a)] = Find (b);
}
int cmpXY (node a, node b) {
	if (a.x == b.x) return a.y < b.y;
	return a.x < b.x;
}
int cmpYX (node a, node b) {
	if (a.y == b.y) return a.x < b.x;
	return a.y < b.y;
}
int make() {
	if (n & 1 ) return 0;
	for (int i = 2; i <= n; i += 2) {
		if (Axy[i - 1].x == Axy[i].x) {
			getT (i, i - 1);
			ans += Axy[i].y - Axy[i - 1].y;
		}
		else return 0;
	}
	for (int i = 2; i <= n; i += 2) {
		if (Ayx[i - 1].y == Ayx[i].y) {
			getT (Ayx[i - 1].Pxy, Ayx[i].Pxy);
			ans += Ayx[i].x - Ayx[i - 1].x;
		}
		else  return 0;
		if (pos[Ayx[i - 1].x ] + 1 != pos[Ayx[i].x ])
			for (int j = head[pos[Ayx[i - 1].x ] + 1];
                           j < head[pos[Ayx[i].x ]] - 1; j += 2)
				if (Axy[j].y < Ayx[i].y && Ayx[i].y < Axy[j + 1].y) return 0;
	}
	for (int i = 2; i <= n; i++)
		if (Find(i) != Find(i-1))
			return 0;
	return ans;
}
int main() {
	scanf ("%d", &n);
	for (int i = 1; i <= n; i++) {
		scanf ("%d %d", &Axy[i].x, &Axy[i].y);
		Axy[i].x += INF, Axy[i].y += INF;
	}
	sort (Axy + 1, Axy + n + 1, cmpYX);
	for (int i = 1; i <= n; i++) {
		Axy[i].Pyx = i;
		Ayx[i] = Axy[i];
	}
	sort (Axy + 1, Axy + n + 1, cmpXY);
	int now = -1, t = 0;
	for (int i = 1; i <= n; i++) {
		Ayx[Axy[i].Pyx].Pxy = i, f[i] = i;
		if ( Axy[i].x != now ) {
			now = Axy[i].x, head[++t] = i;
			pos[now] = t;
		}
	}
	printf ("%d", make() );
	return 0;
}

SGU 128.Snake,布布扣,bubuko.com

时间: 2024-10-23 07:37:14

SGU 128.Snake的相关文章

sgu 128

论文啊,04年一个人的论文. 原来线段树还可以这么用. 贴代码. #include<cstdio> #include<iostream> #include<algorithm> using namespace std; const int MAX=10005; class BIT { public: int a[MAX<<1]; void insert(int pos,int x) { while(pos<MAX*2) { a[pos]+=x; pos

小游戏●贪吃蛇1(利用二维数组制作)

利用二维数组编写简单贪吃蛇小游戏,由于是初学C#,用的是单线程,所以蛇不会自动前进 代码及简要分析如下: 1 //定义地图,0为空,1为墙,2为蛇,3为食物 2 int[,] map = new int[15, 15]{ 3 {1,1,1,1,1,1,1,1,1,1,1,1,1,1,1}, 4 {1,2,0,0,0,0,0,0,0,0,0,0,0,0,1}, 5 {1,0,0,0,0,0,0,0,0,0,0,0,0,0,1}, 6 {1,0,0,0,0,0,0,0,0,0,0,0,0,0,1},

SGU 438 The Glorious Karlutka River =) 拆点+动态流+最大流

The Glorious Karlutka River =) Time Limit:500MS     Memory Limit:262144KB     64bit IO Format:%I64d & %I64u Submit Status Practice SGU 438 Appoint description: Description A group of Mtourists are walking along the Karlutka river. They want to cross

sgu Kalevich Strikes Back

这道题就是求一个大矩形被n个矩形划分成n+1个部分的面积,这些矩形之间不会相交,可能包含.. 1 #include <cstdio> 2 #include <cstring> 3 #include <vector> 4 #include <algorithm> 5 #define maxn 120100 6 using namespace std; 7 8 long long s[maxn]; 9 vector<int>g[maxn]; 10 i

数学计数原理(P&#243;lya,高精度):SGU 294 He&#39;s Circles

He's Circles He wrote n letters "X" and "E" in a circle. He thought that there were 2n possibilities to do it, because each letter may be either "X" or "E". But Qc noticed that some different sequences of letters ca

sgu Ice-cream Tycoon

题意:供应商提供n块价格为c的冰淇淋,一个学生想买n块冰淇淋,手中的钱数总共有t元,为了不让买n块冰淇淋所花费的钱数不超过t元,先尽可能卖给这个学生便宜的冰淇淋. 如果这个学生不能买到所需要的冰淇淋则输出“UNHAPPY”,能则输出“HAPPY”. 1 #include <cstdio> 2 #include <cstring> 3 #include <algorithm> 4 #define maxn 200000 5 using namespace std; 6 7

sgu 463 - Walking around Berhattan

K - Walking around Berhattan Time Limit:250MS     Memory Limit:65536KB     64bit IO Format:%I64d & %I64u Submit Status Practice SGU 463 Description As you probably know, Berhattan is a district of Berland's largest city and it consists of equal squar

OpenCV学习代码记录—— Snake轮廓

很久之前学习过一段时间的OpenCV,当时没有做什么笔记,但是代码都还在,这里把它贴出来做个记录. 代码放在码云上,地址在这里https://gitee.com/solym/OpenCVTest/tree/master/OpenCVTest #include <opencv2/core.hpp> #include <opencv2/highgui.hpp> #include <opencv2/imgproc.hpp> #include <opencv2/legac

为什么8位符号数表示 -128~127

在这里不得说两样东西.数制和码制. 正数和负数的数制,码制的差异导致.导致了他们表达方式的不同. 但是,这样做是为了达到在二进制之间的运算直接实现正负数的直接的运算. 原码,反码,补码.之间的规则我就不用说了,我想大家都知道. 下面来说一下在补码的表达形式中,各位的意义: -2N-1  2N-2 ~~~ 23 22 21 20 最高位为符号位取的是负数,之后的其他位为正数 现在我们来举一个例子,来验证这个补码的规则: (-5)原码=[1000 0101]=-1(4+1)=-5 (-5)反码=[1