ZOJ 3470 Magic Squares

本文介绍了一种在特殊网格环境中进行导航的机器人寻路算法。该算法通过判断目标位置所在的层级,并针对不同的边界条件,计算出可达的相邻区块编号,以便于快速下达指令。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

Magic Squares

Time Limit: 2 Seconds      Memory Limit: 65536 KB


One day, the astronauts from China arrived in a planet that they have never been before. First, they sent a robot called AAA to explore the environment as usual.

However, AAA became confused as soon as it departed from the aerostat: it found that the surface of the planet was divided into many blocks we call magic squares, each block is marked by an unique integer in a special order(as shown in the left graph). Fortunately, AAA is so clever that it soon found the relationship between these blocks and the Descartes coordinate system (as shown in the right graph).

Before each movement, AAA would send its current block number to the monitor, then move to the right position the monitor order it to. Assuming that the monitor would only order AAA to move to the block neighbored to the current block. We say two blocks are neighbor if they share one same edge.

To complete the task in time, the monitor need to respond to the request of the robot as soon as possible. But the computing progress may be too complicated for beings. So they now turn to you, an excellent programmer, help them list the blocks the AAA can reach at the time in order to sent command to the robot in a short time.

Input

The first line of input is the number of test cases T, then T lines follow, each is a test case with only one positive integers n no larger than 2,000,000,000.

Output

The output consists of exactly T lines, one line for each case.
Line i (1 <= i <= T) should contain an increasing sequence of integers separated by single spaces -- the numbers of the blocks that the robot could reach (with its current block numbered n).

Sample Input

1
5

Sample Output

4 6 16 18



先判断数字所处的层数,然后分8种情况(在四个拐角处或是在四条边上)来推往里或往外一层的相邻的两个数字(因为四个数字中一定有两个是比其小1和大1的数字其他两数字是不同层的,需要分情况讨论),最后可以将8种情况整理成4种情况进行编写 ~

代码如下:

#include<iostream>
#include<cstdlib>
#include<cstring>
#include<cstdio>
#include<cmath>

using namespace std;

int save[5];

void s_save(int x, int y, int m, int n)
{
    save[0] = x;
    save[1] = y;
    save[2] = m;
    save[3] = n;
}

int dif(int num, int i, int dig, int d)
{
    if(num < dig)
    {
        s_save(num - d + 8 - 2 * i,num - 1,num + 1,num + d + 2 * i);
        return 1;
    }
    else if(num == dig)
    {
        s_save(num - 1, num + 1, num + d + 2 * i, num + d + 2 * (i + 1));
        return 1;
    }
    return 0;
}

void solve(int num, int cov, int dig, int d)
{
    int flag = 0;
    dig += cov;
    flag = dif(num, 0, dig, d); //从上 边开始推
    if(!flag)  //判断是否在左 边上
    {
        dig += cov * 2;
        flag = dif(num, 1, dig, d);
    }
    if(!flag)  //判断是否在下 边上
    {
        dig += cov * 2 + 1;
        flag = dif(num, 2, dig, d);
    }
    if(!flag)  //判断是否在右 边上
    {
        dig += cov * 2 + 1;
        flag = dif(num, 3, dig, d);
    }
    if(!flag)  //判断是否在转完一圈的 上边上
    {
        s_save(num - d,num - 1,num + 1,num + d + 8);
    }
}

void find_cov(int num) //确定元素所在层数
{
    int d = 3, cov = 0, dig = 1;
    while(1)
    {
        if(cov)
            d += 8;
        dig += d;
        if(num <= dig)
            break;
        ++cov;
    }
    if(num == 1)
        s_save(2,4,6,8);
    else
        solve(num, cov, dig - d, d);
}

int main()
{
#ifdef test
    freopen("in.txt", "r", stdin);
#endif
    int t, num;
    scanf("%d", &t);
    while(t--)
    {
        scanf("%d", &num);
        find_cov(num);
        printf("%d %d %d %d\n",save[0],save[1],save[2],save[3]);
    }
    return 0;
}



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值