HDU 1548---A strange lift(搜索&&最短路)

本文介绍了一种基于电梯上下楼限制的最短路径问题,提供了两种解决方案:宽度优先搜索(BFS)与迪杰斯特拉算法(Dijkstra),并详细展示了C语言实现代码。


题意:电梯每层有一个不同的数字,例如第n层有个数字k,那么这一层只能上k层或下k层,但是不能低于一层或高于n层,
      给定起点与终点,要求出最少要按几次键。

思路:此题较为简单,只有两个方向,那么抽象为二叉树。又因为所找的目标节点已知,且要求最短路,因此将所有情况
      记录下来,满足宽度优先原则。


代码实现:




方法二:
    • #include <stdio.h>  
    • #include <string.h>  
    • #include <algorithm>  
    • #include <queue>  
    • using namespace std;  
    •   
    • int n,s,e;  
    • int ss[205],vis[205];  
    •   
    • struct node  
    • {  
    •     int x,step;  
    • };  
    •   
    • int check(int x)  
    • {  
    •     if(x<=0 || x>n)  
    •     return 1;  
    •     return 0;  
    • }  
    •   
    • int BFS()  
    • {  
    •     queue<node> Q;  
    •     node a,next;  
    •     int i;  
    •     a.x = s;  
    •     a.step = 0;  
    •     vis[s] = 1;  
    •     Q.push(a);  
    •     while(!Q.empty())  
    •     {  
    •         a = Q.front();  
    •         Q.pop();  
    •         if(a.x == e)  
    •         return a.step;  
    •         for(i = -1;i<=1;i+=2)  
    •         {  
    •             next = a;  
    •             next.x +=i*ss[next.x];  
    •             if(check(next.x) || vis[next.x])  
    •             continue;  
    •             vis[next.x] = 1;  
    •             next.step++;  
    •             Q.push(next);  
    •         }  
    •     }  
    •     return -1;  
    • }  
    •   
    • int main()  
    • {  
    •     int i,j;  
    •     while(~scanf("%d",&n),n)  
    •     {  
    •         scanf("%d%d",&s,&e);  
    •         for(i = 1;i<=n;i++)  
    •         scanf("%d",&ss[i]);  
    •         memset(vis,0,sizeof(vis));  
    •         printf("%d\n",BFS());  
    •     }  
    •   
    •     return 0;  
    • }

方法三:

一开始的想法是搜索,而且搜索也是可行的,不过既然这道题出在了最短路的专题里面,自然也要尝试下最短路的做法,
要注意的是,这道题是单向边,我们只要让map里面的值全部为1就可以统计次数了
 
最短路的Dijkstra
  1. #include <stdio.h>  
  2. #include <string.h>  
  3. #include <algorithm>  
  4. using namespace std;  
  5.   
  6. const int inf = 1<<30;  
  7.   
  8. int n;  
  9. int map[205][205];  
  10. int a[205],cnt;  
  11. int vis[205],cast[205];  
  12.   
  13. void Dijkstra(int s,int e)  
  14. {  
  15.     int i,j,min,pos;  
  16.     memset(vis,0,sizeof(vis));  
  17.     for(i = 0; i<n; i++)  
  18.         cast[i] = map[s][i];  
  19.     cast[s] = 0;  
  20.     vis[s] = 1;  
  21.     for(i = 1; i<n; i++)  
  22.     {  
  23.         min = inf;  
  24.         for(j = 0; j<n; j++)  
  25.         {  
  26.             if(cast[j]<min && !vis[j])  
  27.             {  
  28.                 pos = j;  
  29.                 min = cast[j];  
  30.             }  
  31.         }  
  32.         if(min == inf)  
  33.             break;  
  34.         vis[pos] = 1;  
  35.         for(j = 0; j<n; j++)  
  36.         {  
  37.             if(cast[pos]+map[pos][j]<cast[j] && !vis[j])  
  38.                 cast[j] = cast[pos]+map[pos][j];  
  39.         }  
  40.     }  
  41. }  
  42.   
  43. int main()  
  44. {  
  45.     int i,j,s,e,x,y;  
  46.     while(~scanf("%d",&n),n)  
  47.     {  
  48.         scanf("%d%d",&s,&e);  
  49.         s--,e--;  
  50.         for(i = 0; i<n; i++)  
  51.             for(j = 0; j<n; j++)  
  52.                 map[i][j] = inf;  
  53.         for(i = 0; i<n; i++)  
  54.         {  
  55.             scanf("%d",&a[i]);  
  56.             if(i+a[i]<n)  
  57.                 map[i][i+a[i]] = 1;  
  58.             if(i-a[i]>=0)  
  59.                 map[i][i-a[i]] = 1;  
  60.         }  
  61.         Dijkstra(s,e);  
  62.         printf("%d\n",cast[e]==inf?-1:cast[e]);  
  63.     }  
  64.   
  65.     return 0;  

另一种Dijkstra代码:

#include<stdio.h> #include<string.h> #define M 1000000 int n,a,b,dis[201],cost[202][201];

void dijkstra() {  int i,j,d,min,mark[201];  for(i=1;i<=n;i++)   dis[i]=cost[a][i]; //dis[i]代表源点到i点的距离  memset(mark,0,sizeof(mark)); //标记数组初始化  dis[a]=0;//到本身距离为0  for(i=1;i<n;i++){   min=M;   for(j=1;j<=n;j++){//选最短路径    if(!mark[j]&&dis[j]<min){     min=dis[j];     d=j;    }   }   f(min==M)//没有最短路径了,可以返回,当然不返回也行,效率低点    return;   mark[d]=1;//把已选的标记   for(j=1;j<=n;j++)    if(!mark[j]&&cost[d][j]+dis[d]<dis[j])//核心:有点像状态转移方程     dis[j]=dis[d]+cost[d][j];  } }

int main() {  int i,j,k[201];  while(scanf("%d",&n),n){   scanf("%d%d",&a,&b);   for(i=1;i<=n;i++){    for(j=1;j<=n;j++)     cost[i][j]=M; //初始距离默认为无穷大   }   for(i=1;i<=n;i++){    scanf("%d",&k[i]);    if(i+k[i]<=n) //合法才处理     cost[i][i+k[i]]=1; //这就是对应能到的层数    if(i-k[i]>=1)     cost[i][i-k[i]]=1;   }   dijkstra();   if(dis[b]<M) //如果没有到达    printf("%d\n",dis[b]);   else    puts("-1");  }  return 0; }




评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值