题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=1548
题目大意:
有一个建筑有N层,里面有一架电梯。给你一个起点层数和一个终点层数。there is a number Ki(0 <= Ki <= N) on every floor,在每一层都有一个按钮,按钮上面有一个数字,表示可以上或者下Ki层。当然,如果大于N或者小于1是不可能的。。然后你可以由起点开始选择上或者下(重复……),当你到达终点为止(或者不可能到达终点为止)。求你需要按按钮的次数,不能到达则输出-1.
解题思路:
这道题可以灰常巧妙的转换为一道最短路题目,对第i层,按钮数字为button[i],则如果满足相加<=N,则把i到i+button[i]的路径长度设为1(巧妙将按钮次数转换为路径长度),同理,相减如果满足>=1,则把i到i-button[i]的路径长度设为1.则最后输出终点的最短路的长度即可。。。。
代码如下:
#include<iostream>
#include<cstdio>
#include<cstring>
#include<string>
#include<algorithm>
using namespace std;
#define MAX 0x3f3f3f3f
#define N 210
int dis[N], map[N][N], button[N];
bool visit[N];
int num;
void Dijkstra(int start)
{
int temp, k;
memset(visit, 0, sizeof(visit));
for(int i = 1; i <= num; ++i)
dis[i] = map[start][i];
dis[start] = 0;
visit[start] = 1;
for(int i = 1; i <= num; ++i)
{
temp = MAX;
for(int j = 1; j <= num; ++j)
if(!visit[j] && temp > dis[j])
temp = dis[k = j];
if(temp == MAX) break;
visit[k] = 1;
for(int j = 1; j <= num; ++j)
if(!visit[j] && dis[j] > dis[k] + map[k][j])
dis[j] = dis[k] + map[k][j];
}
}
int main()
{
int start, end;
while(scanf("%d", &num) && num)
{
memset(dis, 0, sizeof(dis));
memset(button, 0, sizeof(button));
for(int i = 1; i <= num; ++i)
for(int j = 1; j <= num; ++j)
map[i][j] = MAX;
scanf("%d%d", &start, &end);
for(int i = 1; i <= num; ++i) //每层只有1个数字表示可以上或者下button[i]层
{
scanf("%d", &button[i]);
if(i + button[i] <= num) //上
map[i][i + button[i]] = 1;
if(i - button[i] >= 1) //下
map[i][i - button[i]] = 1;
}
/*for(int i = 1; i <= num; ++i) //题目理解错误,以为每层楼梯都有N个按钮,其实每层只有一个按钮
for(int j = 1; j <= num; ++j)
{
if(i + button[j] <= num)
map[i][i + button[j]] = 1;
if(i - button[j] >= 1)
map[i][i - button[j]] = 1;
}*/
Dijkstra(start);
if(dis[end] == MAX) printf("-1\n");
else printf("%d\n", dis[end]);
}
return 0;
}