转自: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;
}

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

  1. 2012年华为杯校园编程大赛决赛 类别:软件C/C++语言

    2012年华为杯校园编程大赛决赛 类别:软件C/C++语言 编程题(共1题,100分.请上机编写程序,按题目要求提交文件.测试用例不对考生公开,凡不满足提交要求导致不能运行或用例不通过,不予评分.) ...

  2. 硬核粉丝 | 清华双胞胎“YCY Dance Now”杀进超越杯编程大赛决赛

    作者 | Jane 出品 | AI科技大本营(id:rgznai100) 从"黄蓉 AI 换脸 杨幂"."首届杨超越编程大赛"."cxk 流量或打篮球 ...

  3. 2014华为编程大赛题目2:笨笨熊搬家打包篇

    注:2014华为编程大赛题目2 下面贴出我的代码,经过多次测试后,无问题, 所以想共享下,也看看大家的思路. 笨笨熊搬家打包篇 描述:森林里的笨笨熊今天可开心啦--他买了新房子,乔迁新禧要搬新家了.因 ...

  4. 2014届华为校园招聘机试题

    华为2014校园招聘的机试题目和2013年的完全一样. 一.题目描述(60分): 通过键盘输入一串小写字母(a~z)组成的字符串.请编写一个字符串过滤程序,若字符串中出现多个相同的字符,将非首次出现的 ...

  5. 英雄会第一届在线编程大赛解题思路

    其实往往看到编程题目,作为一个java程序员,往往觉得语言不占优势,好像写了也没什么机会,我个人觉得其实在快慢效率上,真正的还是思想,大胆写,java有那么好的api,java源代码,好的开源社区,写 ...

  6. 华为机试题2014 java_2014届华为校园招聘机试题(java实现)

    首先要感谢, 博主Hackbuteer1.提供的关于2014年的华为面试题目.这里运行环境是windows7,eclipse.jdk为1.8.0_45.好了直接上题目.代码,及分析. 一.题目描述(6 ...

  7. 2015届华为校园招聘机试题

    第一题(60分):        按要求分解字符串,输入两个数M,N:M代表输入的M串字符串,N代表输出的每串字符串的位数,不够补0.例如:输入2,8, "abc" ," ...

  8. 2012届华为校园招聘机试题

    1.选秀节目打分,分为专家评委和大众评委,score[] 数组里面存储每个评委打的分数,judge_type[] 里存储与 score[] 数组对应的评委类别,judge_type[i] == 1,表 ...

  9. 2013届华为校园招聘机试题

    笔试题目(机试,共两题)  题目一:子串分离  题目描述:    通过键盘输入任意一个字符串序列,字符串可能包含多个子串,子串以空格分隔.请编写一个程序,自动分离出各个子串,并使用','将其分隔,并且 ...

最新文章

  1. ansible文档官网
  2. python序列类型-Python数值类型和序列类型
  3. 软件常见基础问题总结
  4. java多线程教程_java 基础教程之多线程详解及简单实例
  5. 两列布局 html5,CSS两列布局的N种实现
  6. 【4】搭建Docker私服harbor
  7. spring-boot-starter-parent的主要作用
  8. 宿松的小孤山在安徽省内有名吗?
  9. JStorm如何保证消息不丢失
  10. [转] 如何看透一个人
  11. 技术员 Ghost Win 10(x86/x64)装机版/纯净版 201808
  12. sata和sas硬盘Linux,SAS硬盘与SATA硬盘的功能对比
  13. C# WPF如何设置oxyplot的折线图禁止鼠标滚轮缩放
  14. Android 项目必备(二)--> 启动页 引导页
  15. H5打开支付宝小程序
  16. java unbox_java base-05-Box UnBox 自动装拆箱
  17. javaSE探赜索隐之三<类与对象的爱恨情仇中>
  18. try {}里有一个 return 语句,那么紧跟在这个 try 后的 finally {}里的 code 会不会被执行,什么时候被执行,在 return 前还是后?
  19. 【毕业季话题有奖征文】进击的技术er
  20. 网页中的三种地址详解

热门文章

  1. 如何对系统声音进行选择与设置
  2. 植物纳米探测器简介 | 综述(Nanobiotechnology approaches for engineering smart plant sensors)
  3. 计算机设备管理器不显示网卡,驱动技巧:解决设备管理器中找不到网卡的问题...
  4. 阿里云CentOS7.2清除wnTKYg木马
  5. SpringCloud Alibaba实战第九课 分布式事务理论、DevOps运维
  6. “德阳造”水上智能清污机器人 一次可收集500公斤垃圾
  7. 感想篇:7)知其然与知其所以然,KnowHow与KnowWhy
  8. Linux截图和屏幕视频录制软工具Kazam使用攻略
  9. 矩阵快速幂(矩阵加速)
  10. 查看文章影响因子的插件_你的pubmed又不能显示影响因子了,因为 ……