可以用到的算法:Dijkstra,BFS,DP
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=1548
题意:
有一个特别的电梯,对于第i层按up可升上到i+k[i]层,按down到达i-k[i]层,到达的楼层最高不能超过n层,最低不能小于1层,给你一个起点和终点,问最少可以按几次到达目的地。
思路1:
最短路:把每一层都看成一个节点,问题就可以变成求起点到终点的最短路径问题。
用Dijkstra算法和BFS算法都行
Dijkstra
#include<cstdio>
#include<cstring>
#define maxn 250
#define INF 0x3f3f3f3f
int map[maxn][maxn],dis[maxn];
bool visit[maxn];
int n,start,end;
int dijkstra()
{
if(start==end)
return 0;
int i,j,k;
memset(visit,false,sizeof(visit));
for(i=1;i<=n;i++)
dis[i]=map[start][i];
dis[start]=0;
visit[start]=true;
for(i=1;i<n;i++)
{
int MIN=INF,pos;
for(j=1;j<=n;j++)
if(!visit[j]&&MIN>dis[j])
MIN=dis[j],pos=j;
if(MIN==INF)
return -1;
if(pos==end)
return MIN;
visit[pos]=true;
for(k=1;k<=n;k++)
if(!visit[k]&&dis[pos]+map[pos][k]<dis[k])
dis[k]=dis[pos]+map[pos][k];
}
return -1;
}
int main()
{
while(scanf("%d",&n),n)
{
scanf("%d %d",&start,&end);
memset(map,0x3f,sizeof(map));
for(int i=1;i<=n;i++)
{
int t;
scanf("%d",&t);
if(i+t<=n)
map[i][i+t]=1;
if(i-t>=1)
map[i][i-t]=1;
}
printf("%d\n",dijkstra());
}
return 0;
}
BFS
#include<cstdio>
#include<queue>
#include<cstring>
using namespace std;
#define maxn 250
bool visit[maxn];
int floor[maxn][2];//floor[i][0]表示第i层向上能到的楼层,floor[i][1]则表示向下能到的楼层
int n,start,end;
struct node
{
int pos,t;
}temp,p;
queue<node> q;
int BFS()
{
memset(visit,false,sizeof(visit));
while(!q.empty())
{
temp=q.front();
q.pop();
visit[temp.pos]=true;
if(temp.pos==end)
return temp.t;
int up=floor[temp.pos][0],down=floor[temp.pos][1];
if(up!=-1&&!visit[up])
{
p.pos=up;
p.t=temp.t+1;
q.push(p);
}
if(down!=-1&&!visit[down])
{
p.pos=down;
p.t=temp.t+1;
q.push(p);
}
}
return -1;
}
int main()
{
while(scanf("%d",&n),n)
{
scanf("%d %d",&start,&end);
memset(floor,-1,sizeof(floor));
while(!q.empty())
q.pop();
for(int i=1;i<=n;i++)
{
int t;
scanf("%d",&t);
temp.pos=i;
floor[i][0]=floor[i][1]=-1;
if(i+t<=n)
floor[i][0]=i+t;
if(i-t>=1)
floor[i][1]=i-t;
if(i==start)
{
temp.t=0;
q.push(temp);
}
}
temp=q.front();
printf("%d\n",BFS());
}
return 0;
}
思路2:
DP: dp[i]表示从起点到第i层的按按钮的最少次数
#include<cstdio>
#include<cstring>
#define maxn 250
#define INF 0x3f3f3f3f
int dp[maxn],floor[maxn][2];//floor[i][0]表示第i层向上能到的楼层,floor[i][1]则表示向下能到的楼层
int main()
{
int n,a,b;
while(scanf("%d",&n),n)
{
scanf("%d %d",&a,&b);
memset(floor,-1,sizeof(floor));
for(int i=1;i<=n;i++)
{
int t;
scanf("%d",&t);
if(i+t<=n)
floor[i][0]=i+t;
if(i-t>=1)
floor[i][1]=i-t;
}
memset(dp,0x3f,sizeof(dp));
dp[a]=0;
while(true)
{
int num=0;//记录更新数据的次数
for(int i=1;i<=n;i++) if(dp[i]<INF)
for(int j=0;j<2;j++) if(floor[i][j]!=-1)
if(dp[floor[i][j]]>dp[i]+1)
dp[floor[i][j]]=dp[i]+1,num++;
if(num==0)//无法继续更新
break;
}
if(dp[b]==INF)
dp[b]=-1;
printf("%d\n",dp[b]);
}
return 0;
}