ZOJ 3823 Excavator Contest (2014 Mudanjiang Regional E) (構造)

Excavator Contest

Time Limit: 2 Seconds      Memory Limit: 65536 KB      Special Judge

Bluefly University is famous of excavator technology. Lots of students take part in many excavator-related courses. After the students finish their courses, they will compete in a contest called International Collegiate Excavator Contest (ICEC).

An excavator

This year's ICEC will be held at Marjar University. This is an individual competition that each contestant will start the match one by one.

The task of the contest is to drive an excavator passing a square field. The judge partitioned the field into N × N equal-sized square chunks. Each chunk should be visited exactly one time. The contestant will drive the excavator, starting from and ending at the center of two different boundary chunks.

In order to show off their superb excavator operating skills, the contestants need to drive the excavator with as many as possible turnings. Since the excavator is a kind of large and heavy vehicle, it can only make a turn to left or right at the center of any chunk.

Bob is a student from Marjar University. He wants to win the contest. To fulfill this dream, he needs to drive the excavator with at least N × (N - 1) - 1 turnings. It seems to be a difficult task, so he turns to you for help. Please write a program to find a feasible route for him.

Input

There are multiple test cases. The first line of input contains an integer T indicating the number of test cases. For each test case:

There is only one integer N (2 <= N <= 512).

Output

For each test case, output a matrix with N × N integers indicating the route to pass all the chunks. Bob will drive the excavator passing the chunks in the order of 1, 2, .., N2.

If there are multiple solutions, any one will be acceptable.

Sample Input

2
4
3

Sample Output

2 1 16 15
3 4 13 14
6 5 12 11
7 8 9 10
1 2 3
8 7 4
9 6 5

Hints

route for N=3 or N=4


Author: ZHOU, Yuchen
Source: The 2014 ACM-ICPC Asia Mudanjiang Regional Contest

    解題報告:構造。

    現場賽時冠軍隊弄出來了,也是NB到不行。當時我在弄這題,到比賽結束時才發現有起點和終點必須在邊界上的限制……

    不過就算是這樣,構造方法還是很難想。偶數的構造法如下:

    

    奇數的我一直想不出來,看了其他大神的做法,如下:

    

    整體是中心對稱的,可以認爲這張圖左邊少了兩列。按照這種方式每次加上兩行、兩列,可以構造出所有奇數的情況。

    ok,然後就是編碼了。偶數很好寫,奇數可以預處理,然後根據n的大小打印需要的部分。

#include <iostream>
#include <cstdio>
#include <algorithm>
#include <cstring>
#include <cmath>
#include <queue>
#include <vector>
#include <map>
#include <set>
#include <string>
#include <iomanip>
#include <cassert>
using namespace std;
#pragma comment(linker, "/STACK:1024000000,1024000000")
#define ff(i, n) for(int i=0;i<(n);i++)
#define fff(i, n, m) for(int i=(n);i<=(m);i++)
#define dff(i, n, m) for(int i=(n);i>=(m);i--)
#define travel(e, u) for(int e = u, v = vv[u]; e; e = nxt[e], v = vv[e])
#define bit(n) (1LL<<(n))
#define And(a, b) ((a) & (b))
#define Or(a, b) ((a) | (b))
#define Xor(a, b) ((a) ^ (b))
#define clr(a, b) memset((a), b, sizeof(a))
#define ls (pos<<1)
#define rs (ls|1)
#define lson l, m, ls
#define rson m+1, r, rs
#define mid ((l+r)/2)
typedef long long LL;
typedef unsigned long long ULL;
void work();
int main()
{
#ifdef ACM
    freopen("in.txt", "r", stdin);
#endif // ACM

    work();
    return 0;
}

void scanf(int & x, char ch = 0)
{
    while((ch=getchar()) < '0' || ch > '9');

    x = ch - '0';
    while((ch=getchar()) >= '0' && ch <= '9') x = x * 10 + ch - '0';
}

/***************************************************************************************/

namespace Even
{
int arr[555][555];
int x, y, idx;

void u()
{
    arr[--x][y] = ++idx;
}

void d()
{
    arr[++x][y] = ++idx;
}

void l()
{
    arr[x][--y] = ++idx;
}

void r()
{
    arr[x][++y] = ++idx;
}

void dd()
{
    r(), d(), l(), d();
}

void rr()
{
    d(), r(), u(), r();
}

void ll()
{
    l(), u(), l(), d();
}

void uu()
{
    u(), l(), u(), r();
}
}

namespace Odd
{
int arr[1111][1111];
int x, y, idx;

void u()
{
    arr[--x][y] = ++idx;
    arr[1000-x][1000-y] = -arr[x][y];
}

void d()
{
    arr[++x][y] = ++idx;
    arr[1000-x][1000-y] = -arr[x][y];
}

void l()
{
    arr[x][--y] = ++idx;
    arr[1000-x][1000-y] = -arr[x][y];
}

void r()
{
    arr[x][++y] = ++idx;
    arr[1000-x][1000-y] = -arr[x][y];
}

void dd()
{
    r(), d(), l(), d();
}

void rr()
{
    d(), r(), u(), r();
}

void ll()
{
    l(), u(), l(), d();
}

void uu()
{
    u(), r(), u(), l();
}
}

void init()
{
    using namespace Odd;

    x = 500, y = 500, idx = 0;
    clr(arr, 0x7F);

    arr[x][y] = idx;
    u(), r();

    fff(i, 1, 256) if(i%4 == 1)
    {
        ff(j, i) dd();
        r(), d(), d();
    }
    else if(i%4 == 2)
    {
        ff(j, i) ll();
        l(), l();
    }
    else if(i%4 == 3)
    {
        ff(j, i) uu();
        u(), u(), r();
    }
    else if(i%4 == 0)
    {
        ff(j, i) rr();
    }
}

void work()
{
    init();

    int T;
    scanf("%d", &T);

    fff(cas, 1, T)
    {
        int n;
        scanf("%d", &n);

        if(n == 1)
        {
            puts("1");
        }
        else if(n == 2)
        {
            puts("1 2");
            puts("4 3");
        }
        else if(n == 3)
        {
            puts("1 2 3");
            puts("8 7 4");
            puts("9 6 5");
        }
        else if(n%2 == 0)
        {
            using namespace Even;
            x = 1, y = 1, idx = 0;
            arr[x][y] = ++idx;

            int stp = n/2 - 1;

            fff(i, 1, (n+2)/4)
            {
                ff(j, stp) dd();
                rr();
                d(), r(), u();
                ff(j, stp) uu();
                r();
            }

            fff(i, 1, n) fff(j, 1, n)
            {
                printf("%d", arr[i][j]);
                if(j == n)
                    puts("");
                else
                    printf(" ");
            }
        }
        else
        {
            using namespace Odd;

            int t = (n * (n+2) - 1) / 2;

            int xx, yy;
            ff(i, 1111) ff(j, 1111) if(arr[i][j] == t)
                xx = i, yy = j;
            xx = min(xx, 1000-xx);
            yy = min(yy, 1000-yy);

            int mi = 1<<30;
            fff(i, xx, xx+n-1) fff(j, yy, yy+n-1)
                mi = min(mi, arr[i][j]);

            fff(i, xx, xx+n-1) fff(j, yy, yy+n-1)
            {
                printf("%d", arr[i][j] - mi + 1);
                if(j == yy+n-1)
                    puts("");
                else
                    printf(" ");
            }
        }
    }
}



發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章