HDU 1072 Nightmare BFS

HDU1072迷宫问题解析
本文介绍了一种使用广度优先搜索(BFS)解决迷宫问题的方法,通过跟踪每一步的剩余步数来寻找从起点到终点的最短路径,并特别讨论了遇到特殊点(值为4)时的处理方式。
题意:在 NM 的矩阵内只可以走六步,如果碰到4就可以再走六步,问能不能走出迷宫?(如果能走出,输出最少的秒数,如果不能走出,输出-1。)
思路:BFS呀,我开始蠢,写了DFS。建一个t数组, tij 代表走到 (i,j) 还剩几步可以走,如果碰到4的话,设置一个时间,重新加入队列即可。

http://acm.hdu.edu.cn/showproblem.php?pid=1072

/*********************************************
    Problem : HDU 1072
    Author  : NMfloat
    InkTime (c) NM . All Rights Reserved .
********************************************/

#include <map>
#include <set>
#include <queue>
#include <cmath>
#include <ctime>
#include <cstdio>
#include <cstring>
#include <cstdlib>
#include <iostream>
#include <algorithm>

#define rep(i,a,b)  for(int i = (a) ; i <= (b) ; i ++)
#define rrep(i,a,b) for(int i = (b) ; i >= (a) ; i --)
#define repE(p,u) for(Edge * p = G[u].first ; p ; p = p -> next)
#define cls(a,x)   memset(a,x,sizeof(a))
#define eps 1e-8

using namespace std;

const int MOD = 1e9+7;
const int INF = 0x3f3f3f3f;
const int MAXN = 1e5+5;
const int MAXE = 2e5+5;

struct Node {
    int x,y,t;//t代表走到这一秒最少的时间
    int cost;//消耗的时间
    Node(){}
    Node(int _x,int _y,int _t,int _cost){x = _x ; y = _y ; t = _t;cost = _cost;}
};

typedef long long LL;
typedef unsigned long long ULL;

int T,n,m,k;

queue<Node>q;

int fx[] = {0,1,-1,0,0};
int fy[] = {0,0,0,-1,1};
int sx,sy;
int Map[10][10];
int t[10][10];//走到这一步最短的时间
int ok ;

void BFS() {
    while(!q.empty()) q.pop();
    q.push(Node(sx,sy,6,0));
    t[sx][sy] = 6;
    while(!q.empty()) {

        Node tmp = q.front();
        q.pop();
        // printf("x : %d y : %d tmp : %d cost : %d\n",tmp.x,tmp.y,tmp.t,tmp.cost);
        if(tmp.t == 0) continue;
        if(Map[tmp.x][tmp.y] == 3) {
            ok = 1;
            printf("%d\n",tmp.cost);
            break;
        }
        rep(i,1,4) {
            int tmpx = tmp.x + fx[i];
            int tmpy = tmp.y + fy[i];
            int tmpt = tmp.t - 1;
            if(tmpx >= 1 && tmpx <= n && tmpy >= 1 && tmpy <= m) {
                if(t[tmpx][tmpy] < tmpt) {
                    t[tmpx][tmpy] = tmpt;
                    if(Map[tmpx][tmpy] == 1 || Map[tmpx][tmpy] == 3) {
                        q.push(Node(tmpx,tmpy,tmp.t-1,tmp.cost+1));
                    }
                    else if(Map[tmpx][tmpy] == 4) {
                        t[tmpx][tmpy] = 6;
                        q.push(Node(tmpx,tmpy,6,tmp.cost+1));
                    }
                }
            }
        }
    }
}

void input() {
    scanf("%d %d",&n,&m);
    rep(i,1,n) rep(j,1,m) {
        scanf("%d",&Map[i][j]);
        if(Map[i][j] == 2) {
            sx = i ; sy = j;
        }
    }    
}

void solve() {
    cls(t,0);
    ok = 0;
    BFS();
    if(!ok) puts("-1");
}

int main(void) {
    //freopen("a.in","r",stdin);
    scanf("%d",&T); while(T--) {
    //while(~scanf("%d %d",&n,&m)) {
    //while(scanf("%d",&n),n) {
        input();
        solve();
    }
    return 0;
}
### HDU 1072 C++ 实现解析 HDU 1072 是一个经典的动态规划问题,题目名称为 **Catch That Cow**。该问题的核心在于通过广度优先搜索 (BFS) 来寻找从起点到终点的最短路径步数。 #### 题目描述 给定两个整数 `K` 和 `N`,表示农夫的位置和奶牛的目标位置。农夫可以通过三种方式移动: - 走一步到达 `K + 1` - 走一步到达 `K - 1` - 瞬间传送到 `2 * K` 目标是最少经过多少次操作才能让农夫追上奶牛。 --- #### 解决方案概述 此问题可以建模为图上的 BFS 搜索问题。为了防止重复访问某些节点并优化性能,通常会引入一个标记数组来记录已经访问过的状态。以下是解决方案的关键点: - 使用队列存储当前的状态 `(position, steps)`,其中 `position` 表示当前位置,而 `steps` 则是从起始点出发所花费的操作次数。 - 对于每一个可能的动作(即走一步或瞬间传送),将其加入队列以便后续处理[^1]。 - 如果某个动作超出了合理范围或者已经被访问过,则跳过它以减少不必要的计算开销[^2]。 下面提供了一个完整的C++程序实现这一逻辑: ```cpp #include <bits/stdc++.h> using namespace std; const int MAX_POS = 1e5; // 定义最大可达到的位置 int visited[MAX_POS + 1]; void bfs(int start, int end){ queue<pair<int,int>> q; memset(visited,-1,sizeof(visited)); q.push({start,0}); visited[start]=0; while(!q.empty()){ pair<int,int> current=q.front();q.pop(); if(current.first==end){cout<<current.second<<endl;return;} vector<int> next_positions={current.first*2,current.first+1,current.first-1}; for(auto &next_pos : next_positions){ if(next_pos>=0 && next_pos<=MAX_POS && visited[next_pos]==-1){ visited[next_pos]=current.second+1; q.push({next_pos,visited[next_pos]}); } } } } int main(){ ios::sync_with_stdio(false); cin.tie(NULL); int N,K; cin >> N >> K; bfs(N,K); } ``` 上述代码实现了基于BFS算法求解最小步数的功能,并考虑到了边界条件以及效率优化措施[^3]。 --- #### 关键技术细节说明 - **初始化**: 将所有位置设置成未被访问(-1),仅当某位置第一次被发现时才更新其对应的最少步骤数。 - **终止条件**: 当前探索的位置正好等于目标位置时立即停止搜索并输出结果。 - **剪枝策略**: 只有那些尚未访问且处于合法区间内的新位置才会被列入待考察列表之中[^4]。 ---
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值