您的位置:首页 > 编程语言

第4届华为编程大赛决赛试题解答(棋盘覆盖)

2013-04-17 09:28 381 查看
转自:http://blog.csdn.net/zhoujiaxq/article/details/7917071

http://blog.thpiano.com/?p=579看到有人贴出第四届华为编程大赛决赛试题答案,研究了一下,发现有错误,下面将修改正确的代码贴出。

题目是这样的:

=======================================================================


编程题(共1题,100分。请上机编写程序,按题目要求提交文件。测试用例不对考生公开,凡不满足提交要求导致不能运行或用例不通过,不予评分。)


1. 俄罗斯方块之棋盘覆盖

俄罗斯方块是一款风靡全球的益智类游戏。由俄罗斯人阿列克谢·帕基特诺夫发明,故得此名。俄罗斯方块的基本规则是移动、旋转和摆放游戏自动输出的各种方块,使之排列成完整的一行或多行并且消除得分。由于上手简单、老少皆宜,从而家喻户晓,风靡世界。

本试题是在俄罗斯方块几种常见的方块基础上,在指定大小和障碍的棋盘上,用标准的方块形状,完成对棋盘的覆盖。用于覆盖棋盘的方块可以是下文所给出方块的全集,也可以是其中的任意一个子集,且使用的方块数量不限,形状变化不限。

棋盘大小:

棋盘大小为21行21列的正方形。按照从上到下,从左到右,从1开始,依次进行编号,直到最右下方的格子标识为441。

可选方块:

可选方块为标准的俄罗斯方块形状,包括其标准的旋转变化。基本形状如图所示:



各形状的变化如图所示(字母为方块编号):



障碍说明:

棋盘上仅有一处障碍无法放置方块,障碍可处于棋盘任意位置。障碍为基本形状a及其所有的旋转变化,如图所示:





输入输出要求:

输入文件名为testin.txt,格式如下所示,各数字用空格隔开,各数字表示棋盘格子编号。

2 3 22 23

该输入表示障碍

位于棋盘的左上角。

输出文件名为testout.txt,要求先输出棋盘覆盖结果,再输出未覆盖的格子个数。输出棋盘用21行21列数字/字母表示,其中0表示未覆盖的格子,1表示障碍,字母表示对应方块编号(字母对应关系见“可选方块”一节)。最后输出未覆盖格子个数。这里以6行10列棋盘举例示意输出格式(注意:实际输出应该是21行21列,对应方块形状用对应的字母表示):





要求:

1、 用所提供的方块尽可能覆盖棋盘并输出结果;

2、 在(1)的基础上,棋盘上的空格越少越好。

交付件要求:

C/C++:需要提交可执行文件和压缩打包的源代码工程

JAVA:需要提交压缩打包的整个编码工程目录

构造法说起来也很简单,首先利用对称性和可旋转性,将输入缩减为一种(这里都缩减为

),之后对输入的位置进行考虑:

若位于左上角,则可以通过如下的方式填充:





剩余的空格就是左上的第一个格子,剩下的21x16区域用长条可以完美填充

(右下角也是完全一样)

若不位于左上角或右下角,则可通过加入两个L,变成



的4x3的障碍。将障碍体积变为4x3后,再用长条填充,可以保证填充至只剩1个格子。

被别人一点拨,感觉真的是醍醐灌顶,如此简易的分析方法自己便就是做不到口牙……!

照着这个思路,自己也大致写了下代码:

#include <stdio.h>

#include <stdlib.h>

#include <memory.h>

#define TABLE_SIZE 21

// store the input

int input[4]={0};

// store the hole answer

char table[TABLE_SIZE* TABLE_SIZE];

bool isVertical =false;

void Initialize();

void Output(FILE* f);

void Construct();

int main(){

FILE* fw=fopen("testout.txt","w");

FILE* fp=fopen("testin.txt","r");

if (!fp){

printf("file not found!\n");

return 0;

}

// main loop

while (!feof(fp)){

fscanf(fp,"%d %d %d %d",&input[0],&input[1],&input[2],&input[3]);

Initialize();

Construct();

Output(fw);

}

fclose(fp);

fclose(fw);

return 0;

}

void Initialize(){

int i, j, x, y;

memset(table,'f',sizeof(table));

for (i = 0; i<4;++i){

if (input[i]<1 || input[i]> TABLE_SIZE* TABLE_SIZE){

printf("input number error!\n");

exit(0);

}

--input[i];// input pos start from 1... but I start
from 0

}

//sort input

for (i = 1; i<4;++i){

if (input[i]< input[i- 1]){

int temp = input[i];

for (j= i- 1; j>=0 && input[j]> temp;--j){

input[j + 1]= input[j];

}

input[j + 1]= temp;

}

}

//rotate input to 3x2 if it is 2x3

if (input[1]- input[0]!=1){

isVertical = true;

for (i=0; i<4;++i){

x = input[i]% TABLE_SIZE;

y = input[i]/ TABLE_SIZE;

input[i]= x* TABLE_SIZE+ TABLE_SIZE-1 - y;

}

input[0]^= input[1];

input[1]^= input[0];

input[0]^= input[1];

}

}

void Construct(){

int i, j, x, y;

x = input[0]% TABLE_SIZE;

y = input[0]/ TABLE_SIZE;

if (input[0]==1 || input[0]== TABLE_SIZE* TABLE_SIZE-2 - TABLE_SIZE){//
in the corner (left-top or right-bottom)

if (input[0]==1){

table[0]='0';

}else{

table[TABLE_SIZE * TABLE_SIZE - 1] ='0';

}

for (i=1; i< TABLE_SIZE;++i){

table[i + y * TABLE_SIZE]='a';

table[i - 1 +(y+ 1)* TABLE_SIZE]='a';

}

}else{

//fill it with L in a 4x3 tiny block (3x4 is also useful)

if (y!= TABLE_SIZE-2 && x !=1){

for (i= x- 2; i< x+ 2;++i){

for (j = y; j< y+ 3;++j){

table[i + j * TABLE_SIZE]='c';

}

}

}else{

for (i= x- 1; i< x+ 3;++i){

for (j = y -1; j< y + 2;++j){

table[i + j * TABLE_SIZE]='c';

}

}

}

//leave a hole anywhere

if (table[0]=='f'){

table[0]='0';

}else{

table[TABLE_SIZE - 1]='0';

}

}

// fill the barrier

for (i = 0; i<4;++i){

table[input[i]]='1';

}

}

void Output(FILE* fp){

int i, j;

for (i = 0; i< TABLE_SIZE;++i){

for (j=0; j< TABLE_SIZE;++j){

if (isVertical){

fprintf(fp,"%c ", table[TABLE_SIZE-1 - i + j * TABLE_SIZE]);

}else{

fprintf(fp,"%c ", table[i* TABLE_SIZE+ j]);

}

}

fprintf(fp,"\n");

}

fprintf(fp,"1\n");

}

以上是网友给出的代码,有些小错误,把c和g全部当成c使用了。修改后的如下:

#include <stdio.h>

#include <stdlib.h>

#include <string.h>

#define TABLE_SIZE 21

char table[TABLE_SIZE*TABLE_SIZE];

int input[4] = {0};

bool isVertical = false;

int Initialize()

{

int i,j;

unsigned int Xaxis,Yaxis;

char chTmp = 0;

//首先全部初始化为'f'

memset(table, 'f', sizeof(table));

//检查输入合法性,并将输入都减1,起始为0

for (i = 0; i < 4; ++i){

if (input[i] < 1 || input[i] > TABLE_SIZE * TABLE_SIZE){

printf("input number error!\n");

return -1;

}

--input[i];

}

//升序排列

for (i = 0;i < 3;i++){

for (j = i+1;j < 4;j++){

if (input[i] > input[j]){

chTmp = input[i];

input[i] = input[j];

input[j] = chTmp;

}

}

}

//若障碍是2x3,则旋转成3x2

if (input[1] - input[0] == TABLE_SIZE){

isVertical = true;

for (i = 0;i < 4;i++){

Xaxis = input[i] % TABLE_SIZE;

Yaxis = input[i] / TABLE_SIZE;

input[i] = Xaxis * TABLE_SIZE + TABLE_SIZE - Yaxis - 1;

}

input[0] ^= input[1];//交换input[0]和input[1]的位置

input[1] ^= input[0];

input[0] ^= input[1];

}

return 0;

}

void Construct()

{

unsigned int Xaxis = input[0] % TABLE_SIZE;

unsigned int Yaxis = input[0] / TABLE_SIZE;

int i,j;

//首先处理位于左上角和右下角的情况

if (input[0] == 1 || input[0] == (TABLE_SIZE-1)*TABLE_SIZE-2){

if (input[0] == 1)//标示出未覆盖的地方

table[0] = '0';

else

table[TABLE_SIZE*TABLE_SIZE-1] = '0';

for (i = 1;i < TABLE_SIZE;i++){

table[Yaxis*TABLE_SIZE+i] = 'a';

table[(Yaxis+1)*TABLE_SIZE+i-1] = 'a';

}

}

//障碍物位于最上一行,左侧填充g,右侧填充c

else if (Yaxis == 0){

table[TABLE_SIZE*TABLE_SIZE-1] = '0';

table[input[0]-1] = 'g';

table[input[0]-2] = 'g';

table[input[0]+TABLE_SIZE-2] = 'g';

table[input[0]+TABLE_SIZE*2-2] = 'g';

table[input[0]+TABLE_SIZE+1] = 'c';

table[input[0]+TABLE_SIZE*2-1] = 'c';

table[input[0]+TABLE_SIZE*2] = 'c';

table[input[0]+TABLE_SIZE*2+1] = 'c';

}

//障碍物位于最下一行,左侧填充g,右侧填充c

else if (Yaxis == TABLE_SIZE-2){

table[0] = '0';

table[input[0]-TABLE_SIZE+2] = 'g';

table[input[0]+2] = 'g';

table[input[0]+TABLE_SIZE+1] = 'g';

table[input[0]+TABLE_SIZE+2] = 'g';

table[input[0]-1] = 'c';

table[input[0]-TABLE_SIZE] = 'c';

table[input[0]-TABLE_SIZE-1] = 'c';

table[input[0]-TABLE_SIZE+1] = 'c';

}

//障碍物位于中间,周围填充c

else{

table[TABLE_SIZE*TABLE_SIZE-1] = '0';

for (i = 0;i < 3;i++){

for (j = 0;j < 4;j++){

table[(Yaxis+i-1)*TABLE_SIZE+Xaxis+j-1] = 'c';

}

}

}

//标示出障碍物的位置

for (i = 0;i < 4;i++){

table[input[i]] = '1';

}

}

void Output(FILE* fp)

{

int i,j;

for (i = 0; i < TABLE_SIZE; ++i){

for (j = 0; j < TABLE_SIZE; ++j){

if (isVertical){

fprintf(fp, "%c ", table[TABLE_SIZE - 1 - i + j * TABLE_SIZE]);

}else{

fprintf(fp, "%c ", table[i * TABLE_SIZE + j]);

}

}

fprintf(fp, "\n");

}

fprintf(fp, "1\n");

}

int main()

{

FILE *fI,*fO;

fI = fopen("testin.txt","r");

if (!fI)

{

printf("testin.txt does not exist!\n");

return -1;

}

fO = fopen("testout.txt","w");

fscanf(fI,"%d %d %d %d", &input[0], &input[1], &input[2], &input[3]);

if (Initialize())

{

printf("Initialize failed!\n");

return -1;

}

Construct();

Output(fO);

fclose(fO);

fclose(fI);

return 0;

}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: