HDOJ 1548 HDU 1548 A strange lift ACM 1548 IN HDU

MiYu原创, 转帖请注明 : 转载自 ______________白白の屋

题目地址:
         http://acm.hdu.edu.cn/showproblem.php?pid=1548
题目描述:
A strange lift
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 ' 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

题目分析:
        这题又是一个标准的  Dijkstra 算法的题目 ( 最短路 ).  要说难度吗?  对我而言吧, 就是 图的生成.
刚开始做的时候自己想复杂了, 以为从不同的楼层开始, 就有不同的走法, 所以开始的时候写循环没写对,
就写成了递归.   结果很杯具的 STACK_OVERFLOW........   在 AMB 神牛的指点发现, 原来是自己想复杂了,
只需要计算出每一个楼层的 上楼 和 下楼就可以了, 当然, 要注意是否越界.  图生成后, 当然就是 DIJKSTRA了.

闲来无事, 又复制一遍 :
            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) 再继续。



代码如下:
#include  < iostream >
using   namespace  std;
const   int  MAX  =   200 ;
const   int  INF  =   0x7FFFFFF ;
int  N,A,B;
int  g[MAX + 1 ][MAX + 1 ];
int  hash[MAX + 1 ];
int  path[MAX + 1 ];
int  K[MAX + 1 ];
int  Dijkstra (  int  beg ,  int  end )
{
    path[beg] 
=   0 ;
    hash[beg] 
=   false ;
    
while  ( beg  !=  end )
    {
            
int  m  =  INF, temp;
            
for  (  int  i  =   1 ; i  <=  N;  ++  i )
            {
                  
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;
            
if  ( m  ==  INF )
                 
break ;
            hash[beg] 
=   false ;
    }
    
if  ( path[end]  ==  INF )
         
return   - 1 ;
    
return  path[end]; 
}

int  main ()
{
    
while  ( scanf (  " %d%d%d " & N,  & A,  & B ) , N )
    {
            
for  (  int  i  =   0 ; i  <=  MAX;  ++  i )
            {
                  hash[i] 
=   true ;
                  path[i] 
=  INF;
                  
for  (  int  j  =   0 ; j  <=  MAX;  ++  j )
                  {
                        g[i][j] 
=  INF;
                  } 
            }
            
for  (  int  i  =   1 ; i  <=  N;  ++  i )
            {
                  scanf ( 
" %d " , & K[i] );
            } 
            
for  (  int  i  =   1 ; i  <=  N;  ++  i )
            {
                  
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
}


SO 代码:
#include  < iostream >
using   namespace  std;
const   int  MAX  =   200 ;
const   int  INF  =   0x7FFFFFF ;
bool  UP  =   true ;
bool  DOWN  =   false ;
int  N,A,B;
int  g[MAX + 1 ][MAX + 1 ];
int  hash[MAX + 1 ];
int  path[MAX + 1 ];
int  K[MAX + 1 ];

int  Dijkstra (  int  beg ,  int  end )
{
    path[beg] 
=   0 ;
    hash[beg] 
=   false ;
    
while  ( beg  !=  end )
    {
            
int  m  =  INF, temp;
            
for  (  int  i  =   1 ; i  <=  N;  ++  i )
            {
                  
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;
            
if  ( m  ==  INF )
                 
break ;
            hash[beg] 
=   false ;
    }
    
if  ( path[end]  ==  INF )
         
return   - 1 ;
    
return  path[end]; 
}

bool  setGraph (  int  n,  bool  flag )
{
     
if  ( flag ) 
     {
          
if  ( n  +  K[n]  <=  N )
          {
               g[ n ][ n 
+  K[n] ]  =   1 ;
               setGraph ( n 
+  K[n], UP );
               setGraph ( n 
+  K[n], DOWN );
          }  
     }
     
else
     {
          
if  ( n  -  K[n]  >=   1  )
          {
               g[ n  ][ n 
-  K[n] ]  =   1 ;
               setGraph ( n 
-  K[n], UP );
               setGraph ( n 
-  K[n], DOWN ); 
          } 
     }
     
return   true ;
}
int  main ()
{
    
while  ( scanf (  " %d%d%d " & N,  & A,  & B ) , N )
    {
            
for  (  int  i  =   0 ; i  <=  MAX;  ++  i )
            {
                  hash[i] 
=   true ;
                  path[i] 
=  INF;
                  
for  (  int  j  =   0 ; j  <=  MAX;  ++  j )
                  {
                        g[i][j] 
=  INF;
                  } 
            }
            
for  (  int  i  =   1 ; i  <=  N;  ++  i )
            {
                  scanf ( 
" %d " , & K[i] );
            } 
            
for  (  int  i  =   1 ; i  <=  N;  ++  i )
            {
                  setGraph ( i, UP );
                  setGraph ( i, DOWN ); 
            }
            cout 
<<  Dijkstra ( A, B )  <<  endl;
    }
    
return   0
}

你可能感兴趣的:(ACM)