《编程思维与实践》1092.显示路径

《编程思维与实践》1092.显示路径

题目

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-4n3tj4w8-1684243470675)(C:\Users\Administrator\AppData\Roaming\Typora\typora-user-images\image-20230516202419474.png)]

思路

注意到 x + y = ± 2 0 ± 2 1 . . . ± 2 n x+y=±2^0±2^1...±2^n x+y=±20±21...±2n为奇数,所以一个点能到达的必要条件为|x|+|y|是奇数.

特别地,我们称|x|+|y|为一个点和原点间的曼哈顿距离.

观察到:

①走一步时有 ∣ x ∣ + ∣ y ∣ = 1 ∈ ( 0 , 2 1 ] |x|+|y|=1\in(0,2^1] x+y=1(0,21] ;

②走两步时有 ∣ x ∣ + ∣ y ∣ ∈ ( 0 , 2 2 ] , 可能取值为 1 和 3 , 其中新增的 3 ∈ ( 2 1 , 2 2 ] |x|+|y|\in(0,2^2],可能取值为1和3,其中新增的3\in(2^1,2^2] x+y(0,22],可能取值为13,其中新增的3(21,22] ;

③走三步时有 ∣ x ∣ + ∣ y ∣ ∈ ( 0 , 2 3 ] , 可能取值为 1 , 3 , 5 和 7 , 其中新增的 5 和 7 ∈ ( 2 2 , 2 3 ] |x|+|y|\in(0,2^3],可能取值为1,3,5和7,其中新增的5和7\in(2^2,2^3] x+y(0,23],可能取值为1,3,57,其中新增的57(22,23] ;

④走四步时有 ∣ x ∣ + ∣ y ∣ ∈ ( 0 , 2 4 ] , 可能取值为 1 , 3 , 5 , 7 , 9 , 11 , 13 和 15 , 其中新增的 9 , 11 , 13 和 15 ∈ ( 2 3 , 2 4 ] |x|+|y|\in(0,2^4],可能取值为1,3,5,7,9,11,13和15,其中新增的9,11,13和15\in(2^3,2^4] x+y(0,24],可能取值为1,3,5,7,9,11,1315,其中新增的9,11,1315(23,24] .

初步猜测|x|+|y|是奇数也是该点能到达的充分条件.

下面给出更强的结论和证明:
结论 :   ∣ x ∣ + ∣ y ∣ 为奇数且满足   2 k − 1 − 1 < ∣ x ∣ + ∣ y ∣ ≤ 2 k − 1 , 则该点可到达 , 且所需的最少步数为 k . 证明 : 设点 ( ∣ x ∣ , ∣ y ∣ ) 可以到达 , 则由必要性知 ∣ x ∣ + ∣ y ∣ 为奇数 , 当走 k 步到达时满足 0 < ∣ x ∣ + ∣ y ∣ ≤ 2 0 + 2 1 + . . . + 2 k − 1 = 2 k − 1 , 当走 k − 1 步到达时满足 0 < ∣ x ∣ + ∣ y ∣ ≤ 2 k − 1 − 1 , 所以当可到达的点对应的 ∣ x ∣ + ∣ y ∣ 落在 ( 2 k − 1 − 1 , 2 k − 1 ] 中时 , 至少需要走 k 步 , 下面证明走 k 步时可以到达 ( 0 , 2 k − 1 ] 中的所有奇数值 : 当步数为 1 时可以可以到达点 ( 0 , 1 ) , 对应的 ∣ x ∣ + ∣ y ∣ = 1 落在 ( 0 , 1 ] 中 , 满足要求 ; 下设步数小于 k 时结论成立 , 证明步数为 k 的情形 : 由归纳假设 , 走 k − 1 步可到达的点满足 ∣ x ∣ + ∣ y ∣ 均落在 ( 0 , 2 k − 1 − 1 ] 的奇数值中 , 不妨设 y = 0 , 则 ∣ x ∣ = 1 , 3 , 5... 2 k − 1 − 1 , 再走一步 , 则 : ∣ x − 2 k − 1 ∣ = 1 , 3 , 5... 2 k − 1 − 1 , 2 k − 1 + 1 , 2 k − 1 + 3... 2 k − 1 所以走 k 步时可以到达 ( 0 , 2 k − 1 ] 中的所有奇数值 , 那么由前面的论述可知可到达的点对应的 ∣ x ∣ + ∣ y ∣ 落在 ( 2 k − 1 − 1 , 2 k − 1 ] 中时所需的最少步数即为 k 步 . 结论:\,|x|+|y|为奇数且满足\, 2^{k-1}-1<|x|+|y|≤2^k-1,则该点可到达,且所需的最少步数为k.\\ 证明:设点(|x|,|y|)可以到达,则由必要性知|x|+|y|为奇数,\\ 当走k步到达时满足0<|x|+|y|≤2^0+2^1+...+2^{k-1}=2^k-1,\\ 当走k-1步到达时满足0<|x|+|y|≤2^{k-1}-1,\\ 所以当可到达的点对应的|x|+|y|落在(2^{k-1}-1,2^k-1]中时,至少需要走k步,\\ 下面证明走k步时可以到达(0,2^k-1]中的所有奇数值:\\ 当步数为1时可以可以到达点(0,1),对应的|x|+|y|=1落在(0,1]中,满足要求;\\ 下设步数小于k时结论成立,证明步数为k的情形:\\ 由归纳假设,走k-1步可到达的点满足|x|+|y|均落在(0,2^{k-1}-1]的奇数值中,\\ 不妨设y=0,则|x|=1,3,5...2^{k-1}-1,再走一步,则:\\ |x-2^{k-1}|=1,3,5...2^{k-1}-1,2^{k-1}+1,2^{k-1}+3...2^{k}-1 \\ 所以走k步时可以到达(0,2^k-1]中的所有奇数值,\\ 那么由前面的论述可知可到达的点对应的|x|+|y|落在(2^{k-1}-1,2^k-1]中时所需的最少步数即为k步. 结论:x+y为奇数且满足2k11<x+y2k1,则该点可到达,且所需的最少步数为k.证明:设点(x,y)可以到达,则由必要性知x+y为奇数,当走k步到达时满足0<x+y20+21+...+2k1=2k1,当走k1步到达时满足0<x+y2k11,所以当可到达的点对应的x+y落在(2k11,2k1]中时,至少需要走k,下面证明走k步时可以到达(0,2k1]中的所有奇数值:当步数为1时可以可以到达点(0,1),对应的x+y=1落在(0,1],满足要求;下设步数小于k时结论成立,证明步数为k的情形:由归纳假设,k1步可到达的点满足x+y均落在(0,2k11]的奇数值中,不妨设y=0,x1,3,5...2k11,再走一步,:x2k1=1,3,5...2k11,2k1+1,2k1+3...2k1所以走k步时可以到达(0,2k1]中的所有奇数值,那么由前面的论述可知可到达的点对应的x+y落在(2k11,2k1]中时所需的最少步数即为k. {}}
剩下需要解决的问题变为如何走使步数最少且能到达终点?

逆向考虑:从终点往原点走,则只需要使每步走完后的曼哈顿距离比之前小即可(越来越靠近原点).

判断依据: |x|和|y|的大小 , 大的先变可以让整体更加接近原点.

如下图所示:

>

注意的点:

1.如果终点为原点直接输出0.

2.路径可以开一个数组记录,也可以等递归调用结束后直接输出.

代码

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

void Path(long long x,long long y,int k)
{
	if(k)
	{
		long long d=((long long)1)<<(k-1);   //2^{k-1} 第k步走的距离
  		if(llabs(x)>llabs(y))    //x和y不可能相等 不然和为偶数 
		{
			if(x>0)     //左走 
			{
				Path(x-d,y,k-1);  //递归调用后输出
				printf("E");   //倒着向左=正着向右 
			}	
			else 
			{
				Path(x+d,y,k-1);
				printf("W");    
			}	
		} 
		else
		{
			if(y>0)     
			{
				Path(x,y-d,k-1);
				printf("N");   
			}	
			else 
			{
				Path(x,y+d,k-1);
				printf("S");    
			}	
		}
	}
}

int main()
{
    long long x,y;
    scanf("%lld%lld",&x,&y);
    if(x==0&&y==0)   //
    {
    	printf("0\n");
	}
	else
	{
		long long temp=(x>0?x:-x)+(y>0?y:-y);  //绝对值相加
		if(temp%2==0) 
		{
			printf("-1\n");
		}
		else
		{
			long long judge=1;
			int k=0;
			while(judge<temp+1)
			{
				judge*=2;
				k++;   //最少步数
			}
			printf("%d\n",k);
			Path(x,y,k);
		}
	}
    return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值