hdu 1548 A strange lift BFS 解法

2 篇文章 0 订阅

 

 

//不用STL 写的BFS, 要用head 和 tail 标记 step 、 layer 数组。

// step 用来记录BFS 遍历的所有节点, layer 用来记录节点当前的层数 : layer[tail] = layer[head] + 1

// 在一些要求记录最短路径的题型中,

// layer 可以用来记录前驱节点: layer[tail ] = head; //

// 然后 layer 从 后往前找到原路径,如 : http://blog.csdn.net/hongxdong/archive/2010/03/19/5397192.aspx

    1. for ( int j = pre[tail]; j!= 0; j = pre[j])
    2. {
    3.         ans = ' ' + ans;
    4.         ans = char(way[j] + '0') + ans;
    5. }

 

#include <stdio.h>

using namespace
std;


int
main()
{

    int
n, a, b;
    int
step[1000];  // 记录节点列表.
    bool
visited[1000];  // 判断节点是否访问过.
    int
layer[10000];  // 记录每个节点所处搜索树的层数
    int
dist[1000];  // 每层楼移动的距离.
    int
head, tail, up, down;  // head 指向step 的头部, 用以访问保存在step 的节点.  tail 指向 step 的尾部用以添加节点.
    while
(scanf("%d", &n) && n)
    {

        scanf ("%d %d", &a, &b);
        for
(int i = 1; i <= n; i++)
        {

            scanf("%d", &dist[i]);

            visited[i] = false;
        }

        if
(a == b)
        {

            printf("0/n"); continue;
        }

        head = 0; tail = 1;
        step[head] = a;
        bool
flag = false;
        while
(head < tail)  // 节点访问未完成.
        {

            if
(!visited[step[head]])  // step[head] 楼层未被访问
            {

                down = step[head] - dist[step[head]];  // 向下走.
                if
(down > 0 && !visited[down])
                {

                    step[tail] = down;//保存未访问的节点

                    layer[tail] = layer[head] + 1;  // 保存上面节点的层数
                    if
(step[tail] == b)  //如果到达b 楼层.
                    {

                        printf("%d/n", layer[tail]); // 打印出目标节点的层数, 即最少步数.
                        flag = true;
                        break
;
                    }

                    tail++; // 后移step 尾部.
                }

                up = step[head] + dist[step[head]];
                if
(up <= n && !visited[up])
                {

                    step[tail] = up;
                    layer[tail] = layer[head] + 1;
                    if
(step[tail] == b)
                    {

                        printf("%d/n", layer[tail]);
                        flag = true;
                        break
;
                    }

                    tail++;
                }

                visited[step[head]] = true;
            }

            head++; // 访问一个节点结束, 将step 的头部后移.
        }

        if
(flag != true)
            printf("-1/n");
    }
}

下面是用STL 写的, 明显简单得多。

#include <iostream>
#include <vector>
#include <string>
#include <queue>
using namespace std;

 

int main()
{
    int n, a, b;
    freopen("in.txt", "r", stdin);
    vector<int > v(1000);
    vector<bool > visited(1000);
    vector<int > step(1000);
    vector<int > f(10000);

    while (true)
    {
        cin>>n;
        if (n == 0)
            break;

        cin>>a>>b;

        for (int i = 1; i <= n; i++)
        {
            cin>>v[i];
            visited[i] = false;
            f[i] = 0;
        }
        if (a == b)
        {
            cout<<"0"<<endl;
            continue;
        }
        step.clear();
        step.push_back(a);

        int i = 0;
        bool flag = false;

        while (i != step.size())
        {
            if (!visited[step[i]])
            {
                if (step[i] == b)
                {
                    flag = true;
                    break;
                }
                if (step[i] - v[step[i]] > 0 && !visited[step[i] - v[step[i]]] )
                {
                    step.push_back(step[i] - v[step[i]]);
                    f[step.size() - 1] = f[i] + 1;
                }
                if (step[i] + v[step[i]] <= n && !visited[step[i] + v[step[i]]] )
                {
                    step.push_back(step[i] + v[step[i]]);
                    f[step.size() - 1] = f[i] + 1;
                }
                visited[step[i]] = true;
            }
            i++;
        }

        if (flag == true)
        {
            cout<<f[i]<<endl;
        }
        else
        {
            cout<<"-1"<<endl;
        }
    }
}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值