HDU 1548-A strange lift

2 篇文章 0 订阅
1 篇文章 0 订阅

可以用到的算法: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;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值