sgu128
来源:互联网 发布:sql server 2008 补丁 编辑:程序博客网 时间:2024/06/06 01:14
题目:
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
40 00 33 33 0
Sample Output
12
Author: Alex Y. Suslov, Herman "Smash" NarkaytisResource: 5th Southern Subregional Contest. Saratov 2002Date: 2002-10-10
题解:
1.题目要求每条线段必须与x轴或y轴平行,所以每横行、竖行上必须有2的倍数个点
2.线段的构造是唯一的,画个图就知道了
3.可以先构造出图,再判断出线段是否相交
4.将与y轴平行的线段和与x轴平行的线段端点构造成线段树,从左到右依次扫描,遇到与x轴平行的线段的左端点,则插入它的横坐标,遇到右端点,则删除它的横坐标,遇到与y轴平行的线段,则判断在该线段范围(不算端点)内是否有点,如果有点,则相交,图形不合法
5.如遇到横坐标相同,则先处理与x轴平行的线段的右端点,再处理与y轴平行的线段,最后处理与x轴平行的线段的左端点
代码:
#include<stdio.h>#include<stdlib.h>#include<string.h>struct point{ int x, y, id;} p[10001];struct edge{ int x1, x2, y1, y2;} line[10001];struct event{ int id, x, type;} eve[30001];struct type_tree{ int a, b, t, l, r;} tree[100001];int n, num, connect[10001][2], ans, cnt, maxy = -1, miny = 99999, treenum;char vis[10001];void imp(){ printf("0\n"); exit(0);}void init(){ scanf("%d", &n); for(int i = 1; i <= n; ++i) { scanf("%d%d", &p[i].x, &p[i].y); p[i].id = i; maxy = p[i].y > maxy ? p[i].y : maxy; miny = p[i].y < miny ? p[i].y : miny; } if(n & 1) imp();}int cmp1(const void *a, const void *b){ struct point *c = (point *) a; struct point *d = (point *) b; if(c->y != d->y) return c->y - d->y; return c->x - d->x;}int cmp2(const void *a, const void *b){ struct point *c = (point *) a; struct point *d = (point *) b; if(c->x != d->x) return c->x - d->x; return c->y - d->y;}int cmp3(const void *c, const void *d){ struct event *a = (event*) c; struct event *b = (event*) d; if(a->x != b->x) return a->x - b->x; return a->type - b->type;}void createpic(){ qsort(p + 1, n, sizeof(point), cmp1); for(int i = 1; i <= n; i += 2) { if(p[i].y != p[i + 1].y) imp(); line[++num].x1 = p[i].x; line[num].x2 = p[i + 1].x; line[num].y1 = line[num].y2 = p[i].y; connect[p[i].id][0] = p[i + 1].id; connect[p[i + 1].id][0] = p[i].id; ans += p[i + 1].x - p[i].x; eve[++cnt].type = 0; eve[cnt].x = p[i + 1].x; eve[cnt].id = num; eve[++cnt].type = 2; eve[cnt].x = p[i].x; eve[cnt].id = num; } qsort(p + 1, n, sizeof(point), cmp2); for(int i = 1; i <= n; i += 2) { if(p[i].x != p[i + 1].x) imp(); line[++num].y1 = p[i].y; line[num].y2 = p[i + 1].y; line[num].x1 = line[num].x2 = p[i].x; connect[p[i].id][1] = p[i + 1].id; connect[p[i + 1].id][1] = p[i].id; ans += p[i + 1].y - p[i].y; eve[++cnt].type = 1; eve[cnt].x = p[i].x; eve[cnt].id = num; }}void dfs(int now){ vis[now] = true; if(!vis[connect[now][0]]) dfs(connect[now][0]); if(!vis[connect[now][1]]) dfs(connect[now][1]);}void check_link(){ dfs(1); for(int i = 1; i <= n; ++i) if(!vis[i]) imp();}int settree(int a, int b){ int now = ++treenum; tree[now].a = a; tree[now].b = b; if((a + b >> 1) > a) { tree[now].l = settree(a, a + b >> 1); tree[now].r = settree(a + b >> 1, b); } return now;}void ins(int y, int id){ int a = tree[id].a, b = tree[id].b; if(b - a <= 1) ++tree[id].t; else { if(y <= a + b >> 1) ins(y, tree[id].l); else ins(y, tree[id].r); tree[id].t = tree[tree[id].l].t + tree[tree[id].r].t; }}void del(int y, int id){ int a = tree[id].a, b = tree[id].b; if(b - a <= 1) --tree[id].t; else { if(y <= a + b >> 1) del(y, tree[id].l); else del(y, tree[id].r); tree[id].t = tree[tree[id].l].t + tree[tree[id].r].t; }}int find(int y1, int y2, int id){ int a = tree[id].a, b = tree[id].b; if(y1 <= a && b <= y2) return tree[id].t; if(b - a <= 1) return 0; int ans = 0; if(y1 <= (a + b >> 1)) ans |= find(y1, y2, tree[id].l); if(y2 > (a + b >> 1)) ans |= find(y1, y2, tree[id].r); return ans;}void check_cross(){ qsort(eve + 1, cnt, sizeof(event), cmp3); settree(miny, maxy); for(int i = 1; i <= cnt; ++i) { int id = eve[i].id; if(!eve[i].type) del(line[id].y1, 1); else if(eve[i].type == 2) ins(line[id].y1, 1); else if(find(line[id].y1, line[id].y2, 1)) imp(); }}int main(){ init(); createpic(); check_link(); check_cross(); printf("%d\n", ans); return 0;}
//ps:很奇怪,把 /2 改成 >> 1就过了。。。
//代码借鉴了网上大爷的。。。
- sgu128
- SGU128 Snake
- sgu128:Snake
- SGU128 Snake
- iOS UITableViewCell 构建个人信息显示公共组件
- LEETCODE: Single Number
- 韩顺平php视频笔记48 函数进阶
- [leetcode 164] Maximum Gap
- 摄像机跟随问题和粒子系统
- sgu128
- 文件——妖哥
- uvaoj 10791 Minimum Sum LCM 类似欧拉定理的写法
- Python 第三章 使用字符串
- 【GEngine】Unity脚本框架、Custom Inspector
- NYOJ 263 精 挑 细 选 (三次扫描)
- 第一篇 安卓系统的介绍及特点
- Java 访问控制权限
- 程序设计基石与实践之使用构造函数初始化对象