ZOJ 3823 Excavator Contest 构造 2014牡丹江现场赛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


题意:从边界开始出发,每个格子均经过一次且仅一次,并且在边界停下来。


思路:....就是构造题嘛,有比较简单的构造办法,但是我的构造方法比较复杂,很不好写。

我说下我是怎么构造出来的。 假设我们已经求出了(N-2) * (N-2) 的行走方法,折数是(N-2) * (N-3) - 1.

我们就补上两行,两列,两行补在上方,两列补在右方,我们假设先走补上去的地方,如果补上去的地方能走出 N*(N-1) - 1 - (N-2)*(N-3) + 1 = 4 * N - 6, 就可以了。

其实这补上去的两行两列顶多只能走4 * N - 7个“折”, 问题来了:在哪里我们能多一个折呢? 就是从补上的地方进到之前就求出来的地方可以多一个“折”。这样就刚好能满足要求了。

我们需要根据N的奇偶分开来处理。我画几个图让大家看一下我的构造办法(我的方法是锻炼码力的方法再见)。

N = 10 的时候是酱紫的:

右边是大致的规律路线:


像根据这个10的怎么推出12的呢?我们只需要从右边多加两列,下面多加两行。然后从右上角往下,再往左,然后进入这个10x10的图里面就行了,你可以算一下,折数是刚好的。

N = 11 的时的图是酱紫的:


走法类似。

人工的走好像不难走,但是用代码感觉不好写啊。 我的做法是从左上角开始走一个类似回行的路径,然后从左下角开始也是走一个回行的路径。最后把还没走到的补上就行了。


代码:

#include <iostream>
#include <string.h>
#include <cstring>
#include <stdio.h>
#define rep(i,a,b) for(int i=(a);i<(b);++i)
#define rrep(i,b,a) for(int i = (b); i >= (a); --i)
#define clr(a,x) memset(a,(x),sizeof(a))
using namespace std;
const int maxn = 512 + 5;
int N;
int ans[maxn][maxn];

int Move[2][4] = { { 1, 0, -1, 0 }, { 0, 1, 0, -1 } };
int Act[4][4] = { { 0, 1, 2, 1 }, { 1, 0, 3, 0 }, { 3, 2, 1, 2 }, { 2, 3, 0, 3 } };

int Do[2][4] = { { 0, 1, 2, 1 }, { 3, 0, 1, 0 } };
bool inRange(int r, int c) { return 0 <= r && r < N && 0 <= c && c < N;  }

void out()
{
	rep(i, 0, N) rep(j,0,N) {
		if (j > 0) printf(" ");
		printf("%d", ans[i][j]);
		if (j == N - 1) puts("");
	}
}

bool Check()
{
	int r = 0, c = 0;
	int turn = 0, dir = 0;
	rep(i, 1, N*N) {
		bool advance = false;
		if (r == 1 && c == 1)
			char a = 'a';
		rep(j, 0, 4) {
			int rr = r + Move[0][j];
			int cc = c + Move[1][j];
			if (!inRange(rr, cc) || ans[rr][cc] != i + 1) continue;
			r = rr; c = cc;
			if (dir != j) ++turn;
			dir = j;
			advance = true;
			break;
		}
		if (!advance) {
			return false;
		}
	}
	printf("%d %d\n", turn, N*(N - 1) - 1);
	return turn <= N*(N - 1) - 1;
}

int tmp[maxn][maxn];
int main()
{
	int T; cin >> T;
	while (T--) {
		scanf("%d", &N);
		if (N == 3) {
			puts("1 2 3");
			puts("8 7 4");
			puts("9 6 5");
			continue;
		}
		if (N & 1) {
			clr(ans, -1);
			int k = N / 2;
			int r = 0, c = 0;
			int step = 1;
			ans[r][c] = step++;
			for (; k > 0; ) {
				rep(j, 0, k) {
					ans[++r][c] = step++;
					ans[r][++c] = step++;
					ans[--r][c] = step++;
					ans[r][++c] = step++;
				}
				ans[++r][c] = step++;
				if (--k == 0) break;
				rep(j, 0, k) {
					ans[++r][c] = step++;
					ans[r][--c] = step++;
					ans[++r][c] = step++;
					ans[r][++c] = step++;
				}
				ans[++r][c] = step++;
				ans[r][--c] = step++;
				if (--k == 0) break;
				rep(j, 0, k) {
					ans[r][--c] = step++;
					ans[--r][c] = step++;
					ans[r][--c] = step++;
					ans[++r][c] = step++;
				}
				ans[r][--c] = step++;
				ans[--r][c] = step++;
				if (--k == 0) break;
				rep(j, 0, k) {
					ans[--r][c] = step++;
					ans[r][++c] = step++;
					ans[--r][c] = step++;
					ans[r][--c] = step++;
				}
				ans[--r][c] = step++;
				ans[r][++c] = step++;
				ans[r][++c] = step++;
				--k;
				//out();
			}
			
			step = N*N; r = N - 1; c = 0;
			ans[r][c] = step--;
			k = N / 2 - 1;
			for (; k > 0; ) {
				rep(j, 0, k) {
					ans[r][++c] = step--;
					ans[--r][c] = step--;
					ans[r][--c] = step--;
					ans[--r][c] = step--;
				}
				ans[r][++c] = step--;
				ans[r][++c] = step--;
				if (--k == 0) break;
				rep(j, 0, k) {
					ans[++r][c] = step--;
					ans[r][++c] = step--;
					ans[--r][c] = step--;
					ans[r][++c] = step--;
				}
				ans[++r][c] = step--;
				ans[++r][c] = step--;
				if (--k == 0) break;
				rep(j, 0, k) {
					ans[r][--c] = step--;
					ans[++r][c] = step--;
					ans[r][++c] = step--;
					ans[++r][c] = step--;
				}
				ans[r][--c] = step--;
				ans[r][--c] = step--;
				if (--k == 0) break;
				rep(j, 0, k) {
					ans[--r][c] = step--;
					ans[r][--c] = step--;
					ans[++r][c] = step--;
					ans[r][--c] = step--;
				}
				ans[--r][c] = step--;
				ans[--r][c] = step--;
				--k;
			}
			
			for (;;) {
				if (r - 1 >= 0 && ans[r - 1][c] == -1) ans[--r][c] = step--;
				else if (c + 1 < N && ans[r][c + 1] == -1) ans[r][++c] = step--;
				else if (r + 1 < N && ans[r + 1][c] == -1) ans[++r][c] = step--;
				else if (c -1 >= 0 && ans[r][c - 1] == -1) ans[r][--c] = step--;
				else break;
			}
		}
		else {
			clr(ans, -1);
			int k = N / 2 - 1;
			int r = 0, c = 0;
			int step = 1;
			ans[r][c] = step++;
			for (; k > 0;) {
				rep(j, 0, k) {
					ans[++r][c] = step++;
					ans[r][++c] = step++;
					ans[--r][c] = step++;
					ans[r][++c] = step++;
				}
				ans[r][++c] = step++;
				rep(j, 0, k) {
					ans[++r][c] = step++;
					ans[r][--c] = step++;
					ans[++r][c] = step++;
					ans[r][++c] = step++;
				}
				ans[++r][c] = step++;
				ans[r][--c] = step++;
				if ( (k -= 2) <= 0) break;
				rep(j, 0, k) {
					ans[r][--c] = step++;
					ans[--r][c] = step++;
					ans[r][--c] = step++;
					ans[++r][c] = step++;
				}
				ans[r][--c] = step++;
				ans[r][--c] = step++;
				rep(j, 0, k) {
					ans[--r][c] = step++;
					ans[r][++c] = step++;
					ans[--r][c] = step++;
					ans[r][--c] = step++;
				}
				ans[--r][c] = step++;
				ans[r][++c] = step++;
				ans[r][++c] = step++;
				k -= 2;
				//out();
			}
			int x = r, y = c, s = step;
			step = N*N; r = N - 1; c = 0;
			ans[r][c] = step--;
			k = (N-1) / 2 - 1;
			for (; k > 0;) {
				rep(j, 0, k) {
					ans[r][++c] = step--;
					ans[--r][c] = step--;
					ans[r][--c] = step--;
					ans[--r][c] = step--;
				}
				ans[--r][c] = step--;
				ans[r][++c] = step--;
				rep(j, 0, k) {
					ans[++r][c] = step--;
					ans[r][++c] = step--;
					ans[--r][c] = step--;
					ans[r][++c] = step--;
				}
				ans[++r][c] = step--;
				ans[++r][c] = step--;
				if ((k -= 2) <= 0) break;
				rep(j, 0, k) {
					ans[r][--c] = step--;
					ans[++r][c] = step--;
					ans[r][++c] = step--;
					ans[++r][c] = step--;
				}
				ans[++r][c] = step--;
				ans[r][--c] = step--;
				rep(j, 0, k) {
					ans[--r][c] = step--;
					ans[r][--c] = step--;
					ans[++r][c] = step--;
					ans[r][--c] = step--;
				}
				ans[--r][c] = step--;
				ans[--r][c] = step--;
				k -= 2;
			}
			r = x; c = y; step = s;
			
			for (;;) {
				if (r-1 >= 0 && ans[r - 1][c] == -1) ans[--r][c] = step++;
				else if (c + 1 < N && ans[r][c + 1] == -1) ans[r][++c] = step++;
				else if (r + 1 < N && ans[r + 1][c] == -1) ans[++r][c] = step++;
				else if (c - 1 >= 0 && ans[r][c - 1] == -1) ans[r][--c] = step++;
				else break;
			}
			
		}
		out();
		/*if (!Check()) {
			printf("Wrong\n");

		}*/
	}
}


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值