题意:
给你n*n的格子,
要求
·一笔画完,不能重复
·入口出口在边界
·只能直走,左右转90度
·转角次数不少于n*n-n-1
这题我觉得是只要构造一个方案即可,我考虑的是奇数把n*n变成一个m*m的子问题(m < n )
( 代码长是因为中间有一段复制了,没用if写,还有写了一个special judge 判断是否构造对了)
偶数则考虑复制图形。
直接上图:
奇数
偶数:
/*
* Author:
* OpenPandora
* Date:
* 2014.10.12
*/
#include <cmath>
#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
using namespace std;
#define ll long long
#define cls(a) memset(a,0,sizeof(a))
#define rise(i,a,b) for(int i=a;i<=b;i++)
#define fall(i,a,b) for(int i=a;i>=b;i--)
int cas, n, a[1025][1025];
bool flag;
int dx[4] = {-1,0,1,0};
int dy[4] = {0,-1,0,1};
void ji()
{
int begin = 0;
int end = n * n + 1;
int x, y, xup = 1,xdown = n,yup = 1,ydown = n, cnt = 0;
while( begin < end )
{
cnt ++;
if( cnt & 1 )
{
y = yup;
fall( i , xdown , xup )
{
a[i][y] = ++ begin;
if( y & 1 ) y ++; else y --;
a[i][y] = ++ begin;
}
yup += 2;
x = xup;
rise( j , yup , ydown )
{
a[x][j] = ++ begin;
if( x & 1 ) x ++; else x --;
a[x][j] = ++ begin;
}
xup += 2;
x = xdown;
fall( j , ydown , yup )
{
a[x][j] = -- end;
x ^= 1;
a[x][j] = -- end;
}
xdown -= 2;
y = ydown;
rise( i , xup , xdown )
{
a[i][y] = ++ begin;
y ^= 1;
a[i][y] = ++ begin;
}
ydown -= 2;
}
else
{
y = yup;
fall( i , xdown , xup )
{
a[i][y] = -- end;
if( y & 1 ) y ++; else y --;
a[i][y] = -- end;
}
yup += 2;
x = xup;
rise( j , yup , ydown )
{
a[x][j] = -- end;
if( x & 1 ) x ++; else x --;
a[x][j] = -- end;
}
xup += 2;
x = xdown;
fall( j , ydown , yup )
{
a[x][j] = ++ begin;
x ^= 1;
a[x][j] = ++ begin;
}
xdown -= 2;
y = ydown;
rise( i , xup , xdown )
{
a[i][y] = -- end;
y ^= 1;
a[i][y] = -- end;
}
ydown -= 2;
}
}
if( flag )
rise( i , 1 , n )
{
printf( "%d" , a[i][1] );
rise( j , 2 , n )
printf( " %d" , a[i][j] );
putchar( '\n' );
}
}
void ou()
{
int x, y = 2, now = 0;
for( int i = 1 ; i <= n ; i ++ )
{
a[i][y] = ++ now;
y = 3 - y;
a[i][y] = ++ now;
}
for( int j = 3 ; j < n - 1 ; j += 4 )
{
y = j;
for( int i = n ; i > 2 ; i -- )
{
a[i][y] = ++ now;
if( y & 1 ) y ++;
else y --;
a[i][y] = ++ now;
}
x = 2;
for( int k = 0 ; k < 4 ; k ++ )
{
a[x][j+k] = ++ now;
x = 3 - x;
a[x][j+k] = ++ now;
}
y = j + 3;
for( int i = 3 ; i <= n ; i ++ )
{
a[i][y] = ++ now;
if( y & 1 ) y ++;
else y --;
a[i][y] = ++ now;
}
}
y = n - 1;
if( n % 4 == 0 )
for( int i = n ; i > 0 ; i -- )
{
a[i][y] = ++ now;
y = n + n - 1 - y;
a[i][y] = ++ now;
}
if( flag )
rise( i , 1 , n )
{
printf( "%d" , a[i][1] );
rise( j , 2 , n )
printf( " %d" , a[i][j] );
putchar( '\n' );
}
}
void judge()
{
int x = 0 , y = 0 , cnt = 0, now = 2, nx, ny;
rise( i , 1 , n )
rise( j , 1 , n )
if( a[i][j] == 1 )
{
x = i; y = j;
}
if( x == 0 ){
cout << n << endl;
puts( "x = 0" );
return;
}
int bx = x, by = y;
while( a[x][y] != n * n )
{
bool find = false;
rise( k , 0 , 3 )
{
if( a[x+dx[k]][y+dy[k]] == now )
{
now ++;
nx = x + dx[k];
ny = y + dy[k];
if( nx == x && x == bx || ny == y && y == by ); else cnt ++;
bx = x;
by = y;
x = nx;
y = ny;
find = true;
break;
}
}
if( !find )
{
puts( "ERROR!" );
break;
}
}
printf( "%d / %d\n" , cnt , n * n - n - 1 );
}
int main()
{
cin >> cas;
flag = true;
while( cas -- )
{
cls( a );
scanf( "%d" , &n );
if( n & 1 ) ji();
else ou();
// for( n = 2 ; n <= 512 ; n ++ )
// {
// if( n & 1 ) ji();
// else ou();
// cout << n << ": ";
// judge();
// }
}
return 0;
}