题目链接 http://acm.hdu.edu.cn/showproblem.php?pid=1548
Problem Description There is a strange lift.The lift can stop can at every floor as you want, and there is a number Ki(0 <= Ki <= N) on every floor.The lift have just two buttons: up and down.When you at floor i,if you press the button "UP" , you will go up Ki floor,i.e,you will go to the i+Ki th floor,as the same, if you press the button "DOWN" , you will go down Ki floor,i.e,you will go to the i-Ki th floor. Of course, the lift can't go up high than N,and can't go down lower than 1. For example, there is a buliding with 5 floors, and k1 = 3, k2 = 3,k3 = 1,k4 = 2, k5 = 5.Begining from the 1 st floor,you can press the button "UP", and you'll go up to the 4 th floor,and if you press the button "DOWN", the lift can't do it, because it can't go down to the -2 th floor,as you know ,the -2 th floor isn't exist.
Input The input consists of several test cases.,Each test case contains two lines.
Output For each case of the input output a interger, the least times you have to press the button when you on floor A,and you want to go to floor B.If you can't reach floor B,printf "-1".
Sample Input 5 1 5 3 3 1 2 5 0
Sample Output 3 |
题目大意:从1-n有n层楼,每层楼有个ki值,每层楼坐电梯只有up和down2个按钮,按下up或者down按钮,则一次性上升或者下降ki楼(越界无效)。 比如有3楼,k[1]=2,k[2]=1,k[3]=3,则在一楼按up直接到3楼,按down无效,在二楼按up到3楼,down到4楼.... 给定初始楼层和目标楼层,求至少按按钮次数。
题解: 可以用最短路径做,把每层楼看作一个点,利用点到点的距离构建一张图,使用迪杰特斯拉算法求单源最短路径。
#include <cstdio>
#include <algorithm>
#include <cstring>
#define MAXN 205
using namespace std;
int graph[MAXN][MAXN]; // 图
int dis[MAXN]; // 到起点的最短距离
bool flag[MAXN]; // 标记是否找到最短路径
int Beg,End; // 起点和终点
int num; // 点数
int input[MAXN];
int INF = 1<<30;
// 迪杰特斯拉算法求单源最短路径
int Dijkstra() {
// 初始化
memset(flag,0,sizeof(flag));
flag[Beg] = true;
int last = Beg; // 上次找到的点
for(int i = 1;i <= num;i++) {
dis[i] = graph[Beg][i];
}
dis[Beg] = 0;
for(int i = 0;i < num-1;i++) {
int Min = INF;
for(int j = 1;j <= num;j++) {
if(flag[j]) continue;
if(dis[j] < Min) {
Min = dis[j];
last = j;
}
}
flag[last] = true;
// 寻找num-1个点的最短距离
for(int j = 1;j <= num;j++) {
// 遍历所有点
if(flag[j])
continue;
if(dis[j] > dis[last] + graph[last][j]) {
// 更新最短距离
dis[j] = dis[last] + graph[last][j];
}
}
}
return dis[End];
}
int main() {
while(scanf("%d",&num) != EOF && num != 0) {
scanf("%d%d",&Beg,&End);
for(int i = 1;i <= num;i++)
scanf("%d",&input[i]);
// 初始化graph数组
for(int i = 1;i <= num;i++)
for(int j = 1;j <= num;j++) {
if(i != j)
graph[i][j] = INF;
}
// 建图
for(int i = 1;i <= num;i++) {
if(i+input[i] <= num)
graph[i][i+input[i]] = 1;
if(i-input[i] >= 1)
graph[i][i-input[i]] = 1;
}
int ret = Dijkstra();
if(ret == INF) {
printf("-1\n");
} else {
printf("%d\n",ret);
}
}
return 0;
}