您的位置:首页 > 其它

UVA 11853(找连通块)

2015-11-12 21:44 246 查看
求连通块问题, 按照紫书上的思路, 构图(每一块受攻击区域作为一个结点)进行DFS, 若有一条路(攻击区域内)能够连通上下边则输出IMPOSSIBLE, 否则就分别计算最靠北(坐标值较大)的出入点.

整个区域是一个大的正方形. 求连通块比较简单, 从那些与区域上边相交的结点出发进行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;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: