移动距离【第六届】【省赛】【A组】

X星球居民小区的楼房全是一样的,并且按矩阵样式排列。其楼房的编号为1,2,3...
当排满一行时,从下一行相邻的楼往反方向排号。
比如:当小区排号宽度为6时,开始情形如下:
1 2 3 4 5 6
12 11 10 9 8 7
13 14 15 .....
我们的问题是:已知了两个楼号m和n,需要求出它们之间的最短移动距离(不能斜线方向移动)
输入为3个整数w m n,空格分开,都在1到10000范围内
w为排号宽度,m,n为待计算的楼号。
要求输出一个整数,表示m n 两楼间最短移动距离。
例如:
用户输入:
6 8 2
则,程序应该输出:
4
再例如:
用户输入:
4 7 20
则,程序应该输出:
5

国际惯例,分析案例理解题意

思路:这道题思路比较容易想到,就是求两个房子间的行号和列号分别作差,再相加,就是题目所求的答案。 如何求出行号和列号呢?那就要根据宽度和题目所给的条件来找出关系式。这里有个特殊的规则就是,每间隔一行,房子就要往反方向排号。

默认行号和列号从1开始,x代表房号。

对于行号:如果 x < w 肯定在第一行

                  否则 我们通过x / w+1可以求得

但有个特殊情况,如果x%w==0说明它是这行中最大的数,也就是w的倍数,那么做除法它可以得到进位,因此不用+1

 

int row(int x){//行号 
	if(x<=w) return 1;
	return x%w==0?x/w:(x/w)+1;
}

 对于列号:如果x<w 那么x就在它楼号所在的列

 列的情况会相对比较复杂,因为有每隔一行就往反方向排号。

所以要分类讨论,分为偶数行和奇数行

由于我们从第一行开始算,所以就是奇数行正常排列,偶数行按反方向排列

123456
121110987
131415161718
242322212019

当w=6时 

奇数行中的14和18

对于楼号14 :(14%6=2)楼号14的确在第2列

对于楼号18:(18%6=0)这时可以观察到它的列号就是w = 6

因此对于模等于0的情况直接赋值为w

偶数行中的12和8

对于楼号12:(12%6=0)楼号其实就在第1列

可以观察到偶数行模0的楼号都是第1列,直接赋值为1

对于楼号8:此时8并不在一个正序的序列中,那就找出规律,比如(8%6=2)但其实它在倒数第2位,所以我们找出一个式子可以满足这个关系(w-(x%w))+1 

int col(int x){//列号 
	if(x<=w) return x;
	if(row(x)%2==1){ //奇数行 
		return x%w==0?w:x%w;
	}else{			//偶数行 
		return x%w==0?1:(w-(x%w))+1;
	} 
}

总结:这种题不难,但需要耐心的找规律。多演算,还有注意找一些特殊的位置,比如边缘位置,看是否满足普遍规律,不满足就单独处理它。 

 全部代码如下:

#include <bits/stdc++.h>
#define endl '\n'
using namespace std;
int w,m,n;
int row(int x){//行号 
	if(x<=w) return 1;
	return x%w==0?x/w:(x/w)+1;
}
int col(int x){//列号 
	if(x<=w) return x;
	if(row(x)%2==1){ //奇数行 
		return x%w==0?w:x%w;
	}else{			//偶数行 
		return x%w==0?1:(w-(x%w))+1;
	} 
}
int main() {
	cin>>w>>m>>n;
	int result = abs(row(m)-row(n))+abs(col(m)-col(n));
	cout<<result;
	return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值