UVA 11853(找连通块)
2015-11-12 21:44
246 查看
求连通块问题, 按照紫书上的思路, 构图(每一块受攻击区域作为一个结点)进行DFS, 若有一条路(攻击区域内)能够连通上下边则输出IMPOSSIBLE, 否则就分别计算最靠北(坐标值较大)的出入点.
整个区域是一个大的正方形. 求连通块比较简单, 从那些与区域上边相交的结点出发进行DFS, 若能够到达某一个与区域的下边相交的结点则说明上下边可以连通.
我觉得比较难的地方反倒在于找坐标值最大的出入点。比如求入点,比较容易想到的是遍历所有与正方形区域的左边相交的点,找出这条边上没有被覆盖的最大坐标就行了。但实现起来还是有些小细节要想好久。实际上不需要对所有与左边相交的点都检查一遍(过于繁琐),只要检查那些DFS路径走到过的而且与左边相交的结点即可。因为不在DFS路径中的结点与DFS过的结点之间必然有一些空隙, 有空隙就可以穿过, 因此不在其DFS路径中的结点不会对出入点造成影响。
整个区域是一个大的正方形. 求连通块比较简单, 从那些与区域上边相交的结点出发进行DFS, 若能够到达某一个与区域的下边相交的结点则说明上下边可以连通.
我觉得比较难的地方反倒在于找坐标值最大的出入点。比如求入点,比较容易想到的是遍历所有与正方形区域的左边相交的点,找出这条边上没有被覆盖的最大坐标就行了。但实现起来还是有些小细节要想好久。实际上不需要对所有与左边相交的点都检查一遍(过于繁琐),只要检查那些DFS路径走到过的而且与左边相交的结点即可。因为不在DFS路径中的结点与DFS过的结点之间必然有一些空隙, 有空隙就可以穿过, 因此不在其DFS路径中的结点不会对出入点造成影响。
#include <iostream> #include <cstdio> #include <cstdlib> #include <cstring> #include <cmath> #include <algorithm> #include <string> #include <vector> #include <set> #include <stack> #include <queue> #include <deque> #include <map> #include <list> #include <cassert> #include <iomanip> struct Point { double x, y; double range; }; using namespace std; bool isAvailable; int N = 0; Point pts[1002]; bool G[1002][1002]; bool isVisited[1002]; double in, out; bool isInteract(int p1, int p2) { // 判断是否相交, 是则返回true return (pts[p1].range + pts[p2].range) >= hypot(pts[p1].x - pts[p2].x, pts[p1].y - pts[p2].y); } void DFS(int i) { if ( !isAvailable ) return; if ( pts[i].y - pts[i].range <= 0 ) { isAvailable = false; return; } isVisited[i] = true; for ( int k = 0; k < N; k++){ if (!isVisited[k] && G[i][k] ) { DFS(k); } } if ( pts[i].x <= pts[i].range ) // 应该只针对DFS路径中走过的区域计算出入点位置 // 因为如果不在DFS路径中的区域与DFS过的区域之间必然有空隙, 有空隙就可以穿过 // 因此不在DFS路径中的区域不会对出入点造成影响 in = min(in, pts[i].y - sqrt(pow(pts[i].range, 2) - pow(pts[i].x, 2))); if ( pts[i].x + pts[i].range >= 1000 ) out = min(out, pts[i].y - sqrt(pow(pts[i].range, 2) - pow(1000 - pts[i].x, 2))); return; } int main( ) { while ( cin >> N ) { isAvailable = true; in = out = 1000; memset(G, 0, sizeof(G)); memset(pts, 0, sizeof(pts)); memset(isVisited, 0, sizeof(isVisited)); for ( int i = 0; i < N; i++ ) { cin >> pts[i].x >> pts[i].y >> pts[i].range; for ( int j = 0; j < i; j++ ) { if ( !G[i][j] && isInteract(i, j) ) { G[i][j] = G[j][i] = true; } } } for ( int i = 0; i < N; i++ ) { if ( !isVisited[i] && pts[i].y + pts[i].range >= 1000 ) { DFS(i); } } if ( isAvailable ) { printf("0.00 %.2f 1000.00 %.2f\n", in, out); } else { cout << "IMPOSSIBLE" << endl; } } system("pause"); return 0; }
相关文章推荐
- 深入理解计算机系统(5)
- 为什么String是不可变的
- hdu 4628 Pieces(状压dp)
- 深入理解BootStrap Item1 -- 学习从现在开始
- STM32入门学习之SysTick系统定时器(STM32F030F4P6基于CooCox IDE)
- Eclipse查找替换巧妙技巧用法
- hdu 2586 How far away?(LCA离线Tarjan算法)
- IQueryable join 的问题
- 【uml】-九种图之活动图(Activity Diagram))
- matlab:矩阵中对NaN的处理方式
- 九度oj-1002-Grading
- android基础控件
- 去除系统快捷方式箭头
- 第一个Sprint冲刺第二天
- oracle学习笔记--pl/sql编程(流程控制)
- JAVA-WEB
- Asp.net获取程序路径
- c语言模拟实现oc引用计数
- 发现一个github的奇葩设定
- 如何在Eclipse统计代码行数