zoukankan      html  css  js  c++  java
  • 第4届华为编程大赛决赛试题解答(棋盘覆盖)

    转自: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 (= 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 (= 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[+ 1]= input[j];
                }
                input[+ 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[+ y * TABLE_SIZE]='a';
                table[- 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 (= y; j< y+ 3;++j){
                        table[+ j * TABLE_SIZE]='c';
                    }
                }
            }else{
                for (i= x- 1; i< x+ 3;++i){
                    for (= y -1; j< y + 2;++j){
                        table[+ 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 (= 0; i<4;++i){
            table[input[i]]='1';
        }
    }

    void Output(FILE* fp){
        int i, j;
        for (= 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;
    }

  • 相关阅读:
    vue less使用/(除号/斜杠),浏览器不识别问题
    antDesignOfVue 表格复选框添加了默认选中状态,点击清空后数据清空,复选框的选中状态不变的问题。
    vue 可多选的日期插件
    antDesignOfVue 走马灯组件不自动定位到第一页
    antDesignOfVue 表格固定列之后出现空白列
    vue 动态添加表格列
    antDesignOfVue 符合条件的表格复选框禁止选中
    更换文件名大小写之后,git远程文件还存在,删除远程仓库的文件/文件夹
    git文件名大小写不敏感,更改文件大小写后无反应。
    记:mysql查询列含中文
  • 原文地址:https://www.cnblogs.com/youngforever/p/3104675.html
Copyright © 2011-2022 走看看