题目描述:
128. Snake
time limit per test: 0.5 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
本以为是计算几何神题,后来经过坎坷的英译汉之后发现其实不算是十分的严格计算几何。
我们很轻易就可以发现同一行的两个相邻点必须连线,那么就可以轻易算出周长L;
难点是如何判断是否满足成圈和不自交的条件。网上有人说可以暴力搞,试了一下,发现真的可以过,92ms AC
可能是数据比较水吧,标准的解法据说是线段数,有空再试试。
贴代码留念:
#include<iostream>
#include<cstring>
#include<cstdio>
#include<set>
#include<algorithm>
#include<vector>
#include<cstdlib>
#define inf 0xfffffff
#define CLR(a,b) memset((a),(b),sizeof((a)))
#define FOR(a,b) for(int a=1;a<=(b);(a)++)
#define fa first
#define se second
using namespace std;
int const nMax = 10010;
int const base = 10;
typedef long long LL;
typedef pair<LL,LL> pij;
int n;
int Fa[nMax];
int ra[nMax];
void init(){
FOR(i,n)Fa[i-1]=i-1;
FOR(i,n)ra[i-1]=1;
}
int find(int x){
return Fa[x]=(Fa[x]==x?x:find(Fa[x]));
}
void Jion(int u,int v){
int x=find(u),y=find(v);
if(x==y)return ;
Fa[x]=y;
ra[y]+=ra[x];
return ;
}
struct point {
int x,y;
int dex;
bool operator <(const point& b)const {
if(x==b.x)return y<b.y;
return x<b.x;
}
void swp(){
swap(x,y);
return ;
}
}p[nMax];
void read(){
scanf("%d",&n);
for(int i=0;i<n;i++){
scanf("%d%d",&p[i].x,&p[i].y);
p[i].dex=i;
}
}
typedef pair<point,point> seg;
vector<seg> px,py;
bool Cross(seg a,seg b){
if(a.fa.x==b.fa.x||a.se.x==b.fa.x){
if(a.fa.y>b.fa.y&&a.fa.y<b.se.y)return true;
return false;
}
if(b.fa.x>a.fa.x&&b.fa.x<a.se.x){
if(a.fa.y>=b.fa.y&&a.fa.y<=b.se.y)return true;
return false;
}
return false;
}
bool check(){
for(int i=0;i<px.size();i++){
for(int j=0;j<py.size();j++){
if(Cross(px[i],py[j]))return false;
}
}
return true;
}
LL work(){
if(n&1)return 0;
init();
LL L(0);
sort(p,p+n);
py.clear();
for(int i=0;i<n;i+=2){
if(p[i].x!=p[i+1].x)return 0;
Jion(p[i].dex,p[i+1].dex);
L+=p[i+1].y-p[i].y;
py.push_back(seg(p[i],p[i+1]));
}
for(int i=0;i<n;i++)p[i].swp();
sort(p,p+n);
px.clear();
for(int i=0;i<n;i+=2){
if(p[i].x!=p[i+1].x)return 0;
L+=p[i+1].y-p[i].y;
Jion(p[i].dex,p[i+1].dex);
p[i].swp();p[i+1].swp();
px.push_back(seg(p[i],p[i+1]));
}
if(!check()) return 0;
if(ra[find(0)]!=n)return 0;
return L;
}
int main(){
read();
printf("%I64d\n",work());
return 0;
}