题目具体信息忘了,不过还能记得主要的信息,大致如下:
1.求外星人两个房子相距的最短距离
2..输入三个数w、m、n,分别表示列数、第一个房子、第二个房子
3.房子排列为从房号1开始,排满当前行后,从下一行的当前列开始,依次填充行中未填充的数字,房号依次递增,当输入w=-6,m=8,n=2时,显示图像部分如下:
图1
4.输出m、n间的最短距离,样例输出为4.
题目分析:
(一)第一种思路
依次计算所有的数据,并填入二维数组,然后按行、列遍历之,求出m、n的距离。
优点:不用寻找图形规律,可暴力破解。
缺点:花费的时间较多,当w、m、n较多时,无法AC。
(二)第二种思路
通过图中显示数据,可以发现数据以为2倍的w为循环显示,那么就可以将数据按照两行划分,依次计算两行,接下来可能有人想到还是遍历数组,那就是又回到第一种思路了。接下来大家看看前两行的数据。
图2
在这里我们假设从左向右为正序,将正序定义为偶数行,逆序定义为奇数行,同时定义i表示当前行,那么在图2中对应的第一行就是第i = 0行,第二行就是第 i = 1行。
那么可以发现偶数行的数据evenData是0 < (i * w) < evenData <= ((i + 1) * w),奇数行的数据oddData是 evenData < oddData <= (i + 1) * w。那么我们怎么把这两行数据表示出来呢?这就是第二种思路的关键了。
大家有没有发现,没两个房子间的距离,最短的走法只有两种,一种先行后列,一种先列后行。不论选取那种方式,都要求走到同行(列)后立即转向,否则就不是所求的最短路径。
解题关键来了,仔细观察图像后就会发现,两个房子间的最短距离是不是可以用行列下标进行运行得到?OK,正解。
那么问题是我们怎么将某个房子号转换为行列下标呢?这就要用到数据结构中的一维数组表示二维数组思想了。
既然我们将数据划分为两行每个模块,那么在进行转换时,就需要按照两行进行转换。
首先,转换行标。行标是最简单的直接除,可以得到式子①,其中的m表示房子序号:
row = m / w ;//①
然后,转换列标。这个就有点技巧了,因为偶数行和奇数行的列标转换是不一样的,偶数行data对2w取余之后,结果都是0<data<=w ,并且列序是正序,那么就可以表示为m % (2 * w) ,其中的;奇数行的data对2w取余后,结果都是(w<data<=2w),这里就要注意列序的相减了,因为是逆序,每行有w个值,那么结果就是(w - m % w)。解决了?还没完呢,因为要知道m最小值为1,而我们要的下标是从0开始的,所以最后还要再减去一,整理之后就可以的出下面的式子②:
col = (m % (2 * w) > w ) ? (w - m % w) : m % (2 * w) - 1 ;//②
最后,我们就要计算n、m的距离了:
dec = abs(n_row - m_row) + abs(n_col - m_col);
其中的n_row、m_row、n_col、m_col可以套用公式①②求得。
到此,程序结束。
最后附上自己写的代码。
如果分析的有什么错误的地方希望各位看官指正,同时也希望有其他更好的解法:-D。
1 #include <iostream> 2 #include <iomanip> 3 #include <math.h> 4 using namespace std; 5 6 int main(){ 7 int w , m , n ; 8 cin >> w >> m >> n ; 9 int m_i = m / w ; 10 int m_j = (m % (2 * w) > w ) ? (w - m % w) : m % (2 * w) ; 11 int n_i = n / w ; 12 int n_j = (n % (2 * w) > w ) ? (w - n % w ) : n % (2 * w) ; 13 cout << m_i << "," << m_j << endl ; 14 cout << n_i << "," << n_j << endl ; 15 cout << abs(m_i - n_i) + abs(m_j - n_j) << endl ; 16 int ww = w * w ; 17 int sum = 0 ; 18 for(int i = 0 ; i < ww ; i += 2){ 19 for(int j = 0 ; j < w ; j++){ 20 cout << setw(5) << sum + j + 1 << " "; 21 } 22 cout << endl ; 23 sum += w ; 24 for(int j = w ; j > 0 ; j--){ 25 cout << setw(5) << sum + j << " "; 26 } 27 sum += w ; 28 cout << endl ; 29 } 30 return 0; 31 }