2012年华为杯校园编程大赛决赛
类别:软件C/C++语言
编程题(共1题,100分。请上机编写程序,按题目要求提交文件。测试用例不对考生公开,凡不满足提交要求导致不能运行或用例不通过,不予评分。)
1. 俄罗斯方块之棋盘覆盖
俄罗斯方块是一款风靡全球的益智类游戏。由俄罗斯人阿列克谢·帕基特诺夫发明,故得此名。俄罗斯方块的基本规则是移动、旋转和摆放游戏自动输出的各种方块,使之排列成完整的一行或多行并且消除得分。由于上手简单、老少皆宜,从而家喻户晓,风靡世界。
本试题是在俄罗斯方块几种常见的方块基础上,在指定大小和障碍的棋盘上,用标准的方块形状,完成对棋盘的覆盖。用于覆盖棋盘的方块可以是下文所给出方块的全集,也可以是其中的任意一个子集,且使用的方块数量不限,形状变化不限。
l 棋盘大小:
棋盘大小为21行21列的正方形。按照从上到下,从左到右,从1开始,依次进行编号,直到最右下方的格子标识为441。
l 可选方块:
可选方块为标准的俄罗斯方块形状,包括其标准的旋转变化。基本形状如图所示:
各形状的变化如图所示(字母为方块编号):
a b
c d
e f
g
l 障碍说明:
棋盘上仅有一处障碍无法放置方块,障碍可处于棋盘任意位置。障碍为基本形状a及其所有的旋转变化,如图所示:
l 输入输出要求:
输入文件名为testin.txt,格式如下所示,各数字用空格隔开,各数字表示棋盘格子编号。
2 3 22 23
该输入表示障碍位于棋盘的左上角。
输出文件名为testout.txt,要求先输出棋盘覆盖结果,再输出未覆盖的格子个数。输出棋盘用21行21列数字/字母表示,其中0表示未覆盖的格子,1表示障碍,字母表示对应方块编号(字母对应关系见“可选方块”一节)。最后输出未覆盖格子个数。这里以6行10列棋盘举例示意输出格式(注意:实际输出应该是21行21列,对应方块形状用对应的字母表示):
0 e 0 0 0 0 f f f f
e e 0 0 0 1 1 g g g
e 0 0 0 1 1 0 0 0 g
a 0 0 0 c 0 d d 0 0
a a 0 0 c 0 d d b 0
0 a 0 0 c c 0 b b b
28
l 要求:
1、 用所提供的方块尽可能覆盖棋盘并输出结果;
2、 在(1)的基础上,棋盘上的空格越少越好。
l 交付件要求
C/C++:需要提交可执行文件和压缩打包的源代码工程
JAVA:需要提交压缩打包的整个编码工程目录
#include <fstream> #include <iostream> using namespace std; /******************************************************************************* * The maximum map width, height and block size *******************************************************************************/ const int M_W = 21; const int M_H = 21; const int M_N = 4; /******************************************************************************* * Current map width, height *******************************************************************************/ int M_CW = M_W; int M_CH = M_H; /******************************************************************************* * Map for game *******************************************************************************/ const int M_S = M_W > M_H ? M_W : M_H; char map[M_S][M_S] = {0}; /******************************************************************************* * Base class *******************************************************************************/ class Base { public: Base(){} virtual ~Base(){} virtual char GetIDC(void) = 0; virtual bool FillAt(int x, int y) = 0; virtual bool RemoveAt(int x, int y) = 0; }; /******************************************************************************* * Block *******************************************************************************/ template<char idc> class Block : public Base { public: /*************************************************************************** * Initialize ***************************************************************************/ Block() { for (int i = 0; i < M_N; i++) { pos[i] = -1; } } virtual ~Block(){} /*************************************************************************** * Get IDC ***************************************************************************/ virtual char GetIDC(void) { return idc; } /*************************************************************************** * Fill at (x, y) ***************************************************************************/ virtual bool FillAt(int x, int y) { bool bret; for (int i = 0; i < 4; i++) { bret = CheckMap(x, y); if (bret) { SetMap(x, y); return true; } RotateRight(); } return false; } /*************************************************************************** * Remove at (x, y) ***************************************************************************/ virtual bool RemoveAt(int x, int y) { for (int i = 0; i < M_N; i++) { if (pos[i] >= 0) { map[pos[i]/M_W][pos[i]%M_W] = '0'; pos[i] = -1; } } return true; } /*************************************************************************** * Check at (x, y) ***************************************************************************/ virtual bool CheckMap(int x, int y) { int i, j; int xbs, ybs; int count = 0; for (i = 0; i < 4; i++) { for (j = 0; j < 4; j++) { if (block[i][j] == 1) { if (count == 0) { xbs = i; ybs = j; } count++; int nx = x+i-xbs; int ny = y+j-ybs; if (nx < 0 || nx >= M_H || ny < 0 || ny >= M_W || map[nx][ny] != '0') { return false; } } } } return true; } /*************************************************************************** * Set at (x, y) ***************************************************************************/ virtual bool SetMap(int x, int y) { int i, j; int xbs, ybs; int count = 0; for (i = 0; i < 4; i++) { for (j = 0; j < 4; j++) { if (block[i][j] == 1) { if (count == 0) { xbs = i; ybs = j; } if (map[x+i-xbs][y+j-ybs] != '0') { return false; } pos[count++] = (x+i-xbs) * 21 + (y+j-ybs) + 1; map[x+i-xbs][y+j-ybs] = idc; } } } return true; } /*************************************************************************** * Show block ***************************************************************************/ static void Show(void) { for (int i = 0; i < 4; i++) { for (int j = 0; j < 4; j++) { cout << (block[i][j] == 1 ? '*' : ' ') << " "; } cout << endl; } } protected: /*************************************************************************** * Rotate Left ***************************************************************************/ static void RotateLeft(void) { int i, j; char tmp_block[4][4]; for (i = 0; i < 4; i++) { for (j = 0; j < 4; j++) { tmp_block[i][j] = block[j][3-i]; } } for (i = 0; i < 4; i++) { for (j = 0; j < 4; j++) { block[i][j] = tmp_block[i][j]; } } } /*************************************************************************** * Rotate right ***************************************************************************/ static void RotateRight(void) { int i, j; char tmp_block[4][4]; for (i = 0; i < 4; i++) { for (j = 0; j < 4; j++) { tmp_block[i][j] = block[3-j][i]; } } for (i = 0; i < 4; i++) { for (j = 0; j < 4; j++) { block[i][j] = tmp_block[i][j]; } } } protected: /*************************************************************************** * Position data ***************************************************************************/ int pos[M_N]; /*************************************************************************** * Graph for block ***************************************************************************/ static char block[4][4]; }; /******************************************************************************* * Graph for block *******************************************************************************/ char Block<'a'>::block[4][4] = { 1, 0, 0, 0, 1, 1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, }; /******************************************************************************* * Graph for block *******************************************************************************/ char Block<'b'>::block[4][4] = { 1, 1, 1, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, }; /******************************************************************************* * Graph for block *******************************************************************************/ char Block<'c'>::block[4][4] = { 1, 1, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, }; /******************************************************************************* * Graph for block *******************************************************************************/ char Block<'d'>::block[4][4] = { 1, 1, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, }; /******************************************************************************* * Graph for block *******************************************************************************/ char Block<'e'>::block[4][4] = { 0, 1, 0, 0, 1, 1, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, }; /******************************************************************************* * Graph for block *******************************************************************************/ char Block<'f'>::block[4][4] = { 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, }; /******************************************************************************* * Graph for block *******************************************************************************/ char Block<'g'>::block[4][4] = { 0, 1, 0, 0, 0, 1, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, }; /******************************************************************************* * Using global variable map as parameter *******************************************************************************/ int solve(void) { int i, j; int count = 0; for (i = 0; i < M_H; i++) { for (j = 0; j < M_W; j++) { if (map[i][j] == '0') { Block<'a'> a; Block<'b'> b; Block<'c'> c; Block<'d'> d; Block<'e'> e; Block<'f'> f; Block<'g'> g; bool bret = false; bret = bret || d.FillAt(i, j); bret = bret || f.FillAt(i, j); bret = bret || c.FillAt(i, j); bret = bret || g.FillAt(i, j); bret = bret || a.FillAt(i, j); bret = bret || e.FillAt(i, j); bret = bret || b.FillAt(i, j); if (bret) { count += 4; } } } } return count; } /******************************************************************************* * Map rotate *******************************************************************************/ void map_rotate() { int i, j; char tmp_map[M_S][M_S]; for (i = 0; i < M_S; i++) { for (j = 0; j < M_S; j++) { tmp_map[i][j] = map[j][M_S-1-i]; } } for (i = 0; i < M_S; i++) { for (j = 0; j < M_S; j++) { map[i][j] = tmp_map[i][j]; } } M_CH ^= M_CW ^= M_CH; M_CW ^= M_CH; } /******************************************************************************* * Check map and solve *******************************************************************************/ int rotate_map_and_solve(void) { /*************************************************************************** * Save map ***************************************************************************/ int i, j; char orig_map[M_H][M_W]; for (i = 0; i < M_H; i++) { for (j = 0; j < M_W; j++) { orig_map[i][j] = map[i][j]; } } /*************************************************************************** * Solve map ***************************************************************************/ char solve_map[M_H][M_W]; int solve_count = solve(); for (i = 0; i < M_H; i++) { for (j = 0; j < M_W; j++) { solve_map[i][j] = map[i][j]; } } /*************************************************************************** * Rotate and solve map ***************************************************************************/ for (i = 0; i < M_H; i++) { for (j = 0; j < M_W; j++) { map[i][j] = orig_map[i][j]; } } map_rotate(); char save_map[M_H][M_W]; for (i = 0; i < M_H; i++) { for (j = 0; j < M_W; j++) { save_map[i][j] = map[i][j]; } } int solve_count_rotate = solve(); if (solve_count_rotate > solve_count) { solve_count = solve_count_rotate; map_rotate(); map_rotate(); map_rotate(); for (i = 0; i < M_H; i++) { for (j = 0; j < M_W; j++) { solve_map[i][j] = map[i][j]; } } } /*************************************************************************** * Rotate and solve map ***************************************************************************/ for (i = 0; i < M_H; i++) { for (j = 0; j < M_W; j++) { map[i][j] = save_map[i][j]; } } map_rotate(); for (i = 0; i < M_H; i++) { for (j = 0; j < M_W; j++) { save_map[i][j] = map[i][j]; } } solve_count_rotate = solve(); if (solve_count_rotate > solve_count) { solve_count = solve_count_rotate; map_rotate(); map_rotate(); for (i = 0; i < M_H; i++) { for (j = 0; j < M_W; j++) { solve_map[i][j] = map[i][j]; } } } /*************************************************************************** * Rotate and solve map ***************************************************************************/ for (i = 0; i < M_H; i++) { for (j = 0; j < M_W; j++) { map[i][j] = save_map[i][j]; } } map_rotate(); for (i = 0; i < M_H; i++) { for (j = 0; j < M_W; j++) { save_map[i][j] = map[i][j]; } } solve_count_rotate = solve(); if (solve_count_rotate > solve_count) { solve_count = solve_count_rotate; map_rotate(); for (i = 0; i < M_H; i++) { for (j = 0; j < M_W; j++) { solve_map[i][j] = map[i][j]; } } } /*************************************************************************** * Set solve map ***************************************************************************/ for (i = 0; i < M_H; i++) { for (j = 0; j < M_W; j++) { map[i][j] = solve_map[i][j]; } } return solve_count; } /******************************************************************************* * Check map and solve *******************************************************************************/ int check_map_and_solve(void) { /*************************************************************************** * Save map ***************************************************************************/ int i, j; char orig_map[M_H][M_W]; for (i = 0; i < M_H; i++) { for (j = 0; j < M_W; j++) { orig_map[i][j] = map[i][j]; } } /*************************************************************************** * Solve map ***************************************************************************/ char solve_map[M_H][M_W]; int solve_count = solve(); for (i = 0; i < M_H; i++) { for (j = 0; j < M_W; j++) { solve_map[i][j] = map[i][j]; } } /*************************************************************************** * Rotate and solve map ***************************************************************************/ for (i = 0; i < M_H; i++) { for (j = 0; j < M_W; j++) { map[i][j] = orig_map[i][j]; } } int solve_count_rotate = rotate_map_and_solve(); if (solve_count_rotate > solve_count) { solve_count = solve_count_rotate; for (i = 0; i < M_H; i++) { for (j = 0; j < M_W; j++) { solve_map[i][j] = map[i][j]; } } } /*************************************************************************** * Rotate and solve map ***************************************************************************/ int xf = -1; int yf = -1; for (i = 0; i < M_H; i++) { for (j = 0; j < M_W; j++) { map[i][j] = orig_map[i][j]; if (map[i][j] == '1' && xf < 0) { xf = i; yf = j; } } } /*************************************************************************** * Find '1' and check if we can add some block ***************************************************************************/ if (xf >= 0) { /*********************************************************************** * Check : * 1 1 1 * 1 1 or 1 1 * 1 ***********************************************************************/ int solve_count_match = 0; if (map[xf][yf+1] == '1') { /******************************************************************* * Add c c c * c *******************************************************************/ if (xf >= 1) { map[xf-1][yf-1] = 'c'; map[xf-1][yf] = 'c'; map[xf-1][yf+1] = 'c'; map[xf][yf-1] = 'c'; solve_count_match += 4; } /******************************************************************* * Add c * c c c *******************************************************************/ if (xf < M_H - 2) { map[xf+1][yf+1] = 'c'; map[xf+2][yf-1] = 'c'; map[xf+2][yf] = 'c'; map[xf+2][yf+1] = 'c'; solve_count_match += 4; } solve_count_match += rotate_map_and_solve(); if (solve_count_match > solve_count) { solve_count = solve_count_match; for (i = 0; i < M_H; i++) { for (j = 0; j < M_W; j++) { solve_map[i][j] = map[i][j]; } } } } else { /******************************************************************* * Add c * c * c c *******************************************************************/ if (yf > 0) { map[xf][yf-1] = 'c'; map[xf+1][yf-1] = 'c'; map[xf+2][yf-1] = 'c'; map[xf+2][yf] = 'c'; solve_count_match += 4; } /******************************************************************* * Add c c * c * c *******************************************************************/ if (yf < M_W - 2) { map[xf][yf+1] = 'c'; map[xf][yf+2] = 'c'; map[xf+1][yf+2] = 'c'; map[xf+2][yf+2] = 'c'; solve_count_match += 4; } solve_count_match += rotate_map_and_solve(); if (solve_count_match > solve_count) { solve_count = solve_count_match; for (i = 0; i < M_H; i++) { for (j = 0; j < M_W; j++) { solve_map[i][j] = map[i][j]; } } } } } /*************************************************************************** * Set solve map ***************************************************************************/ for (i = 0; i < M_H; i++) { for (j = 0; j < M_W; j++) { map[i][j] = solve_map[i][j]; } } return solve_count; } /******************************************************************************* * Test function *******************************************************************************/ void test() { /*************************************************************************** * Clear map ***************************************************************************/ int i, j; for (i = 0; i < M_H; i++) { for (j = 0; j < M_W; j++) { map[i][j] = '0'; } } /*************************************************************************** * Test map ***************************************************************************/ int a, b; for (a = 0; a < M_H; a++) { for (b = 0; b < M_W; b++) { for (i = 0; i < M_H; i++) { for (j = 0; j < M_W; j++) { map[i][j] = '0'; } } if (a < M_H - 2 && b < M_W - 1) { map[a][b] = '1'; map[a+1][b] = '1'; map[a+1][b+1] = '1'; map[a+2][b+1] = '1'; int m = check_map_and_solve(); if (m < 436) { cout << "At " << m <<": (" << a << "," << b <<")" << endl; } } map[i][j] = '0'; } } /*************************************************************************** * Test map ***************************************************************************/ for (a = 0; a < M_H; a++) { for (b = 0; b < M_W; b++) { for (i = 0; i < M_H; i++) { for (j = 0; j < M_W; j++) { map[i][j] = '0'; } } if (a > 0 && a < M_H - 1 && b < M_W - 1) { map[a][b] = '1'; map[a][b+1] = '1'; map[a+1][b] = '1'; map[a+1][b-1] = '1'; int m = check_map_and_solve(); if (m < 436) { cout << "At " << m <<": (" << a << "," << b <<")" << endl; } } map[i][j] = '0'; } } } int main() { /*************************************************************************** * Test function ***************************************************************************/ test(); return 0; /*************************************************************************** * Clear map ***************************************************************************/ for (int i = 0; i < M_H; i++) { for (int j = 0; j < M_W; j++) { map[i][j] = '0'; } } /*************************************************************************** * Read data from input file ***************************************************************************/ int n = 0; ifstream ifs; ifs.open("testin.txt"); if (ifs.is_open()) { while (!ifs.eof()) { int pos = -1; ifs >> pos; if (pos > 0) { n++; pos--; map[pos/M_W][pos%M_W] = '1'; } } ifs.close(); } /*************************************************************************** * Solve this problem ***************************************************************************/ int m = check_map_and_solve(); /*************************************************************************** * Write data to output file ***************************************************************************/ ofstream ofs; ofs.open("testout.txt"); if (ofs.is_open()) { for (int i = 0; i < M_H; i++) { for (int j = 0; j < M_W; j++) { ofs << map[i][j] << " "; } ofs << endl; } ofs << M_H * M_W - n - m << endl; ofs.close(); } return 0; }