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

  • 相关阅读:
    高级特性(4)- 数据库编程
    UVA Jin Ge Jin Qu hao 12563
    UVA 116 Unidirectional TSP
    HDU 2224 The shortest path
    poj 2677 Tour
    【算法学习】双调欧几里得旅行商问题(动态规划)
    南洋理工大学 ACM 在线评测系统 矩形嵌套
    UVA The Tower of Babylon
    uva A Spy in the Metro(洛谷 P2583 地铁间谍)
    洛谷 P1095 守望者的逃离
  • 原文地址:https://www.cnblogs.com/youngforever/p/3104675.html
Copyright © 2011-2022 走看看