对于这道题,我的思路是先列出矩阵的对角线元素的行列值对应的序号(行列值是一样的,这样一个一维数组就够存储了),然后用二分法去搜索序号为n的点夹在哪两个对角线节点之间,然后再在这两个对角线节点之间寻找正确的坐标点,注意行列值为1的时候和行列值为其他的奇数和偶数的时候,总共要分成三种情况来处理,因为对角线节点的行列值不一样的话,点的下一步移动方向不同。下面是AC代码。
节点移动的示意图如下:
#include <stdio.h>
#include <map>
#include <algorithm>
using namespace std;
unsigned int arr[50005]; //arr[i]代表节点 (i,i)的序号为arr[i]
void func(unsigned int n)
{
//先用二分法寻找n号节点夹在那两个对角线节点之间
unsigned int l, r, m;
int row, col;
l = 1;
r = 50000;
while(1)
{
m = (l+r)/2;
if(n>=arr[m] && n<arr[m+1])
break;
else if(n >= arr[m+1])
l = m+1;
else
r = m-1;
}
if(1 == m)
{
if(1 == n)
{
row = 1;
col = 1;
}
else
{
row = 1;
col = 2;
}
goto end;
}
if(m%2 == 0)
{
if(n-arr[m] <= m-1)
{
row = m;
col = m-(n-arr[m]);
}
else
{
row = m+1;
col = (n-arr[m])-m+1;
}
goto end;
}
else
{
if(n-arr[m] <= m-1)
{
row = m-(n-arr[m]);
col = m;
}
else
{
row = (n-arr[m])-m+1;
col = m+1;
}
goto end;
}
end:
printf("%d %d\n", row, col);
}
//初始化对角线上的节点的序号
void init()
{
int i;
int add;
arr[1] = 1;
add = 2;
for(i=2; i<=50000; i++)
{
arr[i] =arr[i-1]+add;
add += 2;
}
}
int main(void)
{
unsigned int N;
init();
while(scanf("%u", &N))
{
if(0 == N)
break;
func(N);
}
}