ACM-奇怪的电梯(广度优先搜索、AC)

奇怪的电梯

Time Limit:1000MS  Memory Limit:65536K
Total Submit:19 Accepted:6

Description

呵呵,有一天我做了一个梦,梦见了一种很奇怪的电梯。大楼的每一层楼都可以停电梯,而且第i层楼(1<=i<=N)上有一个数字Ki(0<=Ki<=N)。电梯只有2个按钮:上,下。上下的层数等于当前楼层上的那个数字。当然,如果不能满足要求,相应的按钮就会失灵。例如:3 3 1 2 5代表了Ki(K1=3,K2=3,……),从一楼开始。在一楼,按“上”可以到4楼,按“下”是不起作用的,因为没有-2楼。那么,从A楼到B楼至少要按几次按钮呢?

Input

有多组测试数据!对于每组测试数据第一行为三个用空格隔开的正整数,表示N,A,B(1≤N≤200, 1≤A,B≤N),第二行为N个用空格隔开的正整数,表示Ki。

Output

对于每组测试数据请输出一行,即最少按键次数,若无法到达,则输出-1。

Sample Input

5 1 5
3 3 1 2 5
10 1 10
8 1 2 3 4 5 6 7 8 9

Sample Output

3
-1

Hint

多组数据输入方法
while (scanf("%d",&n)!=EOF)
{
}
在控制台上用ctrl+Z 代表输入结束.

Source

 

/*
测试数据:
20 13 4
1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1
*/


/*	------------------------------------------------------------------------
	大概想法就是用动态规划来做。

	1、描述最优子结构:
	最少按键次数到达B层,必然也是最少按键次数通过n-1层,所以就产生了一个最优子
	结构,动态规划适用。(还有什么重叠子问题的不是太懂)

	2、递归定义最优解的值
	由1可知,最少按键次数到达B层,必然也是最少按键次数通过n-1,同理也是最少按
	键次数通过n-2..........递归定义...直到是否可以由A层到达以上符合条件的层数。

    3.按自底向上的方式计算最优解的值
	这里利用了两个二维数组,一个FNumTimes[203][3],[203]用来储存总共有多少层
	[X][0]用来该层对应的上下层数字,[X][1]用来储存该层到达B层需要的最少按键次数
	,0表示,该层无法到达B层。[X][2]用来标志该层是否已经遍历过(如果没有这一个,
	我的程序就会出错,因为这里可能会发生重复访问,比如最上面的一组测试数据)。

	另外一个二维数组是用来TimesFNums[203][203],可以在该按键次数下,可以到达
	目标楼层的楼层。前一维用来储存到达目标楼层需要的最少按键次数,分别是0次,
	1次....200次,后一维用来储存在该最少按键次数可以到达目标楼层,对应的楼层数,
	用于下一次迭代。

    总之是先从B层开始出发,寻找能够按一次键就到达B层的有哪些楼层。然后第二轮再
	从这些楼层出发,寻找能够按二次就到达这些楼层的有哪些楼层。。然后第三轮如此
	递归。。直到对每一个子问题求解一次,计算出每一层到达B层需要的最少按键次数

    4、由计算出的结果构造一个最优解
	由于3已经计算出每一层的解,所以直接判断[X][1]是否等于0,是则无法到达,不是
	则输入[X][1]的值。


	-------------------------------------
	状态AC,0MS,440K,代码比较长,1.38K,这是我自己的弱点,总会将问题复杂化,
	向比较复杂解法去想。所以,代码看起来比较乱。。逻辑不清啊~~~

	------------------------------------------------------------------------	*/

#include<stdio.h>
#include<memory.h>
#include<math.h>

int FNumsTimes[203][3] ;
int TimesFNums[203][203] ;

int main(void)
{
	int N = 0 ;
	int A = 0 ;
	int B = 0 ;
	int nCounts = 0 ;
	int nThisTimes = 0 ;
	int i = 0 ;
	int j = 0 ;
	int k = 0 ; 
	int n = 0 ;
	int fCanFind = 0 ;
	int fUnfinish = 1 ;	

	while(scanf("%d%d%d",&N,&A,&B) != EOF)
	{				
		memset(FNumsTimes,0,sizeof(FNumsTimes)) ;
		memset(TimesFNums,0,sizeof(TimesFNums)) ;

		for(i = 1 ; i <= N ; i++)
		{
			scanf("%d",&FNumsTimes[i][0]) ;
		}

		nCounts = 1 ;
		TimesFNums[0][0] = B ;
		fCanFind = 1 ;
		fUnfinish = 1 ;

		for(nThisTimes = 0 ; nThisTimes <= N ; nThisTimes++)
		{
			n = nCounts ;
			nCounts = 0 ;
			if(1 == fCanFind)
			{
				fCanFind = 0 ;

				for(i = 1 ; i <= N ; i++)
				{
					for(j = 0 ; j < n ; j++)
					{
						if(0 == FNumsTimes[i][2] && abs(i - TimesFNums[nThisTimes][j]) == FNumsTimes[i][0]) 
						{
							FNumsTimes[i][2] = 1 ;
							TimesFNums[nThisTimes+1][nCounts] = i ;
							FNumsTimes[i][1] = nThisTimes + 1 ;
							nCounts++ ;
							if(i == A)
							{
								fUnfinish = 0 ;
							}
							fCanFind = fUnfinish ;
						}
					}
				}
			}
		}

		if(A == B)
		{
			printf("%d\n",0) ;
		}
		else if(0 == FNumsTimes[A][1])
		{
			printf("%d\n",-1) ;
		}
		else
		{
			printf("%d\n",FNumsTimes[A][1]) ;
		}
	}
	return 0 ;
}


 

 

#include<stdio.h>
#include<memory.h>
#include<math.h>

int FNumsTimes[203][2] ;
int TimesFNums[203][203] ;

int main(void)
{
	int N = 0 ;
	int A = 0 ;
	int B = 0 ;
	int nCounts = 0 ;
	int nThisTimes = 0 ;
	int i = 0 ;
	int j = 0 ;
	int k = 0 ; 
	int n = 0 ;
	int fCanFind = 0 ;
	int fUnfinish = 1 ;	

	while(scanf("%d%d%d",&N,&A,&B) != EOF)
	{				
		memset(FNumsTimes,0,sizeof(FNumsTimes)) ;
		memset(TimesFNums,0,sizeof(TimesFNums)) ;

		for(i = 1 ; i <= N ; i++)
		{
			scanf("%d",&FNumsTimes[i][0]) ;
		}

		nCounts = 1 ;
		TimesFNums[0][0] = B ;
		fCanFind = 1 ;
		fUnfinish = 1 ;

		for(nThisTimes = 0 ; nThisTimes <= N ; nThisTimes++)
		{
			n = nCounts ;
			nCounts = 0 ;
			if(1 == fCanFind)
			{
				fCanFind = 0 ;

				for(i = 1 ; i <= N ; i++)
				{
					for(j = 0 ; j < n ; j++)
					{
						if(abs(i - TimesFNums[nThisTimes][j]) == FNumsTimes[i][0]) 
						{
							TimesFNums[nThisTimes+1][nCounts] = i ;
							FNumsTimes[i][1] = nThisTimes + 1 ;
							nCounts++ ;
							if(i == A)
							{
								fUnfinish = 0 ;
							}
							fCanFind = fUnfinish ;
						}
					}
				}
			}
		}

		if(A == B)
		{
			printf("%d\n",0) ;
		}
		else if(0 == FNumsTimes[A][1])
		{
			printf("%d\n",-1) ;
		}
		else
		{
			printf("%d\n",FNumsTimes[A][1]) ;
		}
	}
	return 0 ;
}


 

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值