POJ 2049 Finding Nemo

本文介绍了一种基于迷宫的地图搜索算法实现,包括宽度优先搜索(BFS)和深度优先搜索(DFS)两种方法,并通过实例代码展示了如何进行路径查找。特别地,文章讨论了起始位置可能位于迷宫外部的情况。

搜索练习,在数据预处理部分稍微麻烦一下(即初始化迷宫地图部分),AC时还要注意一下Nemo起始位置可能在迷宫外边,这个时候应该直接返回0。

BFS和DFS都在代码里面了!

#include <iostream>
#include <vector>
#include <algorithm>
#include <cstdlib>
#include <cstring>
#include <iomanip>
#include <queue>

using namespace std;

const int MAXLEN = 255;
const int UP = 0, DOWN = 1, LEFT = 2, RIGHT = 3;
int dx[4] = {0, 0, -1, 1};
int dy[4] = {1, -1, 0, 0};

int M, N;
int maze[MAXLEN][MAXLEN];
int door[MAXLEN][MAXLEN][4];// 0 up, 1 down, 3 left, 4 right
int minSteps;

void Dfs(int x, int y, int steps)
{
    if( steps >= minSteps )
	return ;
    if(x >= MAXLEN || y >= MAXLEN || maze[x][y] == -1)
    {
	minSteps = min(minSteps, steps);
	return;
    }
    if( maze[x][y] == 1 ) return;

    maze[x][y] = 1;
    for(int i = 0; i < 4; ++i)
    {
	if( door[x][y][i] )
	{
	    Dfs(x + dx[i], y + dy[i], steps + 1);
	}
    }
    maze[x][y] = 0;
}

void Bfs(int x, int y)
{
    if( x >= MAXLEN || y >= MAXLEN )
    {
	cout << 0 << endl;
	return ;
    }
    queue<pair<pair<int, int>, int> > q;
    q.push( make_pair( make_pair(x, y), 0 ) );
    !maze[x][y]?maze[x][y]=1:NULL;
    while( !q.empty() )
    {
	x = q.front().first.first;
	y = q.front().first.second;
	int level = q.front().second;
	if( maze[x][y] == -1 )
	{
	    cout << level << endl;
	    break;
	}
	q.pop();
	for(int i = 0; i < 4; ++i)
	{
	    if( door[x][y][i] && maze[x+dx[i]][y+dy[i]] != 1)
	    {
		!maze[x+dx[i]][y+dy[i]]?maze[x+dx[i]][y+dy[i]]=1:NULL;
		q.push( make_pair( make_pair(x+dx[i], y+dy[i]), level+1) );
	    }
	}
    }

    if( q.empty() )
	cout << -1 << endl;
}
void InitMaze()
{
    // 0 means (i,j) is part of maze, -1 means no
    for(int i = 0; i < MAXLEN; ++i)
	for(int j = 0; j < MAXLEN; ++j)
	{
	    if( maze[i][j] == 4 )
	    {
		maze[i][j] = 0;
	    }
	    else maze[i][j] = -1;
	}
}
int main()
{
    while( (cin >> M >> N) && (~M || ~N) )
    {
	memset(maze, 0, sizeof(maze));
	memset(door, 0, sizeof(door));

	for(int i = 0; i < M; ++i)
	{
	    int x, y;
	    cin >> x >> y;
	    int t, d;
	    cin >> t >> d;
	    for(int j = 0; j < d; ++j)
	    {
		if( t )
		{
		    maze[x-1][y+j]++;
		    maze[x][y+j]++;
		}
		else 
		{
		    maze[x+j][y-1]++;
		    maze[x+j][y]++;
		}
	    }
	}

	InitMaze();

	for(int i = 0; i < N; ++i)
	{
	    int x, y, t;
	    cin >> x >> y >> t;
	    if( t )
	    {
		door[x-1][y][RIGHT] = 1;
		door[x][y][LEFT] = 1;
	    }
	    else 
	    {
		door[x][y-1][UP] = 1;
		door[x][y][DOWN] = 1;
	    }
	}

	double xBeg, yBeg;
	cin >> xBeg >> yBeg;
	Bfs((int)xBeg, (int)yBeg );
	//minSteps = 0xffff;
	//Dfs((int)xBeg, (int)yBeg, 0);// note that xBeg or yBeg may exceed 200
	/*
	if(minSteps == 0xffff)
	    cout << -1 << endl;
	else 
	    cout << minSteps << endl;
	    */
    }
    return 0;
}


### POJ 2049 编程问题及解决方案 POJ 2049 是一个涉及计算几何的问题,具体来说是关于“最小圆覆盖”(Smallest Enclosing Circle)的算法实现[^6]。该问题的目标是找到一个能够覆盖所有给定点的最小半径圆,并输出其半径。 #### 问题描述 给定平面上的一组点,要求计算出能够覆盖所有这些点的最小圆的半径。输入包含多组测试数据,每组测试数据的第一行是一个整数 \( n \)(\( 1 \leq n \leq 100,000 \)),表示点的数量,随后 \( n \) 行每行包含两个浮点数 \( x \) 和 \( y \),表示点的坐标。 #### 解决方案 最小圆覆盖问题可以通过随机化增量法高效解决。以下是详细的算法步骤和代码实现: 1. **随机化排序**:将所有点随机打乱顺序,以确保算法在最坏情况下的性能。 2. **初始化圆**:初始时假设圆为第一个点为中心、半径为 0 的圆。 3. **逐点扩展**:依次处理每个点,如果当前点不在圆内,则更新圆使其包含该点。 4. **三点确定圆**:通过三点确定一个圆的几何方法来调整圆的位置和大小。 以下是基于 C++ 的代码实现: ```cpp #include <bits/stdc++.h> using namespace std; struct Point { double x, y; }; struct Circle { Point c; double r; }; double dist(Point a, Point b) { return sqrt((a.x - b.x) * (a.x - b.x) + (a.y - b.y) * (a.y - b.y)); } Circle min_circle_cover(vector<Point> &p) { random_shuffle(p.begin(), p.end()); int n = p.size(); Circle res = {p[0], 0}; for (int i = 0; i < n; ++i) { if (dist(res.c, p[i]) > res.r + 1e-8) { res = {p[i], 0}; for (int j = 0; j < i; ++j) { if (dist(res.c, p[j]) > res.r + 1e-8) { res.c.x = (p[i].x + p[j].x) / 2; res.c.y = (p[i].y + p[j].y) / 2; res.r = dist(res.c, p[i]); for (int k = 0; k < j; ++k) { if (dist(res.c, p[k]) > res.r + 1e-8) { double a = p[j].x - p[i].x; double b = p[j].y - p[i].y; double c = p[k].x - p[i].x; double d = p[k].y - p[i].y; double e = a * (p[i].x + p[j].x) + b * (p[i].y + p[j].y); double f = c * (p[i].x + p[k].x) + d * (p[i].y + p[k].y); double g = 2 * (a * (p[k].y - p[j].y) - b * (p[k].x - p[j].x)); res.c.x = (d * e - b * f) / g; res.c.y = (a * f - c * e) / g; res.r = dist(res.c, p[i]); } } } } } } return res; } int main() { int n; while (scanf("%d", &n) != EOF && n) { vector<Point> p(n); for (int i = 0; i < n; ++i) { scanf("%lf %lf", &p[i].x, &p[i].y); } Circle res = min_circle_cover(p); printf("%.2f\n", res.r); } return 0; } ``` #### 算法复杂度分析 上述算法的时间复杂度为 \( O(n) \) 在期望情况下,这是因为每次新增一个点时,只有极少数点会触发圆的重新计算。此外,随机化排序保证了算法在平均情况下的高效性。 ---
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值