题意:

有一个建筑有N层,里面有一架电梯。给你一个起点层数和一个终点层数。在每一层都有一个按钮,按钮上面有一个数字,表示可以上或者下Ki层。然后你可以由起点开始选择上或者下(重复……),当你到达终点为止(或者不可能到达终点为止)。求你需要按按钮的次数,不能到达则输出-1。

 

思路:

这道题可以转换为一道最短路题目,对第i层,按钮数字为k[i],则如果满足相加<=N,则把i到i+k[i]的路径长度设为1(巧妙将按钮次数转换为路径长度),同理,相减如果满足>=1,则把i到i-k[i]的路径长度设为1.则最后输出终点的最短路的长度即可。

 

注意:

(1)有向图。

(2)可走的范围别越界。

CODE:

 

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
using namespace std;

const int SIZE = 1001;
const int INF = 0x3f3f3f3f;
int w[SIZE][SIZE];
int d[SIZE], v[SIZE];
int k[SIZE];
int n;

void Dijkstra(int s)
{
    int i, j;
    for(i = 1; i <= n; i++) d[i] = (i == s)? 0:INF;
    for(i = 1; i <= n ;i++)
    {
        int x, m = INF;
        for(int y = 1; y <= n; y++) if(!v[y] && m > d[y]) m = d[x=y];
        if(m == INF) break;
        v[x] = 1;
        for(int y = 1; y <= n; y++) d[y] <?= d[x] + w[x][y];
    }
    return ;
}


void init()
{
    memset(w, INF, sizeof(w));
    memset(d, 0sizeof(d));
    memset(v, 0sizeof(v));
    memset(k, 0sizeof(k));
}


int main()
{
    int i, j;
    int s, e;
    while(~scanf("%d", &n), n)
    {
        init();
        scanf("%d%d", &s, &e);
        for(i = 1; i <= n; i++)
        {
            scanf("%d", &k[i]);
            if(k[i]+i <= n) w[i][k[i]+i] = 1;
            if(i-k[i] >= 1) w[i][i-k[i]] = 1;
        }
        Dijkstra(s);
        if(d[e] == INF) printf("-1\n");
        else printf("%d\n", d[e]);
    }
    return 0;
}

 

posted on 2012-08-30 16:23  有间博客  阅读(245)  评论(0编辑  收藏  举报