ZOJ 3823 Excavator Contest 构造题

题意:

  给你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;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值