题目地址:
http://acm.hdu.edu.cn/showproblem.php?pid=1548
题目描述:
题目下!
//算法分析 最短路
//Made by syx
//Time 2010年9月1日 09:25:35
/*
Dijkstra算法的基本思路是:
假设每个点都有一对标号 (dj, pj),其中dj是从起源点s到点j的最短路径的长度
(从顶点到其本身的最短路径是零路(没有弧的路),其长度等于零);
pj则是从s到j的最短路径中j点的前一点。
求解从起源点s到点j的最短路径算法的基本过程如下:
1) 初始化。起源点设置为:① ds=0, ps为空;② 所有其他点: di=∞, pi=?;③ 标记起源点s,记k=s,其他所有点设为未标记的。
2) 检验从所有已标记的点k到其直接连接的未标记的点j的距离,并设置:
dj=min[dj, dk+lkj]
式中,lkj是从点k到j的直接连接距离。
3) 选取下一个点。从所有未标记的结点中,选取dj 中最小的一个i:
di=min[dj, 所有未标记的点j]
点i就被选为最短路径中的一点,并设为已标记的。
4) 找到点i的前一点。从已标记的点中找到直接连接到点i的点j*,作为前一点,设置:i=j*
5) 标记点i。如果所有点已标记,则算法完全推出,否则,记k=i,转到2) 再继续。
*/
//HDE 1548
#include <iostream>
using namespace std;
const int MAX = 200;
const int INF = 0x7FFFFFF;//4字节int最大值
int N,A,B;
int g[MAX+1][MAX+1];//存储图
int hash[MAX+1];//存储是否访问
int path[MAX+1];//存储从源到i的最短路径,及特殊路径
#define min(a,b) a>b?b:a
int Dijkstra ( int beg , int end ) //Dijkstra算法,求beg到end的最短路径长
{
path[beg] = 0;
hash[beg] = false;//源点访问
while ( beg != end )
{
int m = INF, temp;
for ( int i = 1; i <= N; ++ i ) //主要是为了计算path(意思见上),之后选path最小的点设置为已访问
{
if ( g[beg][i] != INF )
path[i] = min ( path[i], path[beg] + g[beg][i] );
if ( m > path[i] && hash[i] )
{
m = path[i];
temp = i;
}
}
beg = temp; //把for求出的上个最短路径点设置为源点
if ( m == INF ) //如果这个源点不到未被访问的点,while结束
break;
hash[beg] = false;//这个源点被访问过
}
if ( path[end] == INF )
return -1;
return path[end];
}
int main ()
{
int i;
int K[MAX+1];
while ( scanf ( "%d", &N) , N )
{
scanf("%d%d" , &A , &B);
//初始化hash path g
for (i = 0; i <= MAX; ++ i )
{
hash[i] = true;
path[i] = INF;
for ( int j = 0; j <= MAX; ++ j )
{
g[i][j] = INF;
}
}
for (i = 1; i <= N; ++ i )
{
scanf ( "%d",&K[i] );
}
for (i = 1; i <= N; ++ i )
{
//根据K,求路,保存在g中,只是路的长度是1,1的时候可以用BFS
if ( i + K[i] <= N )
g[ i ][ i + K[i] ] = 1;
if ( i - K[i] >= 1 )
g[ i ][ i - K[i] ] = 1;
}
cout << Dijkstra ( A, B ) << endl;
}
return 0;
}
Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65536/32768 K (Java/Others)
Total Submission(s): 2641 Accepted Submission(s): 944
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.
Here comes the problem: when you is on floor A,and you want to go to floor B,how many times at least he havt to press the button "UP" or "DOWN"?
Input
The input consists of several test cases.,Each test case contains two lines.
The first line contains three integers N ,A,B( 1 <= N,A,B <= 200) which describe above,The second line consist N integers k1,k2,...,kn.
A single 0 indicate the end of the input.
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