移动距离
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
资源约定:
峰值内存消耗 < 256M
CPU消耗 < 1000ms
请严格按要求输出,不要画蛇添足地打印类似:“请您输入…” 的多余内容。
所有代码放在同一个源文件中,调试通过后,拷贝提交该源码。
注意: main函数需要返回0
注意: 只使用ANSI C/ANSI C++ 标准,不要调用依赖于编译环境或操作系统的特殊函数。
注意: 所有依赖的函数必须明确地在源文件中 #include , 不能通过工程设置而省略常用头文件。
提交时,注意选择所期望的编译器类型。
思路:这道题的难处在于你要知道那一行是正方向的,那一行是反方向的,其实很容易发现每w个数就一行,一行正然后一行反,所以我建立了一个索引表,记录每一行的”首个数字“(不考虑方向),然后索引数组中的下标位奇数的时候,说明索引数组中以下标位置处的内容是正方向递增的,并且该下标也是映射到二维数组中的行数,知道了行数和方向,也就能计算出它的列数了。
#include<iostream>
#include<stdlib.h>
using namespace std;
int ans=1;
int PN(int idx[],int x,int &rowline,int& head){
for(int i=1;;i++){
if(x>=idx[i]&&x<idx[i+1]){
rowline=i;
head=idx[i];
if(i%2==1)
return 1;//代表该序列是正方向
else
return 0;//代表该序列是反方向
}
}
}
int main(){
int w,m,n;
cin>>w>>m>>n;
int head=0;
int rowline=0;
int row1,col1,row2,col2;
int testnum=7;
int idx[10000];//索引表
for(int i=1;i<=10000;i++){
if(i%w==0){
idx[ans]=i-w+1;
ans++;
}
}
if(PN(idx,m,rowline,head)){
row1=rowline;
col1=m-head+1;
}else{
row1=rowline;
col1=w-m+head;
}
if(PN(idx,n,rowline,head)){
row2=rowline;
col2=n-head+1;
}else{
row2=rowline;
col2=w-n+head;
}
ans=abs(row1-row2)+abs(col1-col2);
//cout<<row1<<" "<<col1<<endl;
//cout<<row2<<" "<<col2<<endl;
cout<<ans<<endl;
return 0;
}
在网上发现了更为简洁代码,这里也贴出来。
#include <iostream>
#include <cmath>
using namespace std;
// 输入宽度w和房子编号n,返回房子所在行x,列y
void GetPos(int w, int n, int& x, int& y) {
x = (n-1) / w + 1;
y = n % w;
if (y == 0) y = w;
if (x%2 == 0) { // 偶数行要倒着数
y = w - y + 1;
}
}
int main() {
int w, m, n;
int x1, y1, x2, y2;
cin >> w >> m >> n;
GetPos(w, m, x1, y1);
GetPos(w, n, x2, y2);
cout << abs(x1-x2) + abs(y1-y2) << endl;
return 0;
}