算法竞赛入门经典:第八章 高效算法设计 8.9棋盘覆盖

来源:互联网 发布:幼儿园网站整站源码 编辑:程序博客网 时间:2024/05/16 07:22
/*棋盘覆盖:有一个2^k*2^k的方格棋盘,恰有一个方格是黑色的,其他为白色。你的任务是用包含3个方格的L型牌覆盖所有白色方格。黑色方格不能被覆盖,且任意一个白色方格不能同时被两个或更多牌覆盖。下面是L型牌的4种旋转方式。[][]         [][]            []            [][]             []            [][]        [][](1)           (2)            (3)         (4)自析:递归求解到每4个格子组成的正方形时,如果有黑色,进行填充。如果没有,那干啥啊?书析:分治:划分,递归求解(递归边界,k=1时一块牌就够了),合并。把棋盘凤城4块,每一块都是2^k-1 * 2^k-1的。有黑格的那一块可以递归求解,其他三块应该构造出一块黑格子(牛逼)[# ][  ][  ][  ][  ][  ][# ][  ][  ][ #][# ][  ][  ][  ][  ][  ]怎么构造一块黑格子将棋盘保存在一个二维数组中,骨牌号从1开始,特殊方格为0,如果是一个4*4的棋盘,特殊方格为(2,2),那么程序的输出为2 2 3 32 1 1 34 1 0 54 4 5 5相同数字的为同一骨牌。本质:棋盘每次分成4块子棋盘,递归处理含特殊方格的子棋盘,直到这个子棋盘只有一个格子为止。其余三个不含特殊格的子棋盘中,将这个子棋盘的位置设为骨牌号(?),将这个无特殊的子棋盘转换为右特殊方格的子棋盘。输入:0 1(左上角测试)1 3(右上角测试)3 0(左下角测试)2 2 (右下角测试)输出:2 0 3 32 2 1 34 1 1 54 4 5 52 2 3 32 1 3 04 1 1 54 4 5 52 2 3 32 1 1 34 4 1 50 4 5 52 2 3 32 1 1 34 1 0 54 4 5 5*/#include <stdio.h>#define BOARD_SIZE 4int board[BOARD_SIZE][BOARD_SIZE];int g_domino_num;// c1, r1: 棋盘左上角的行号和列号// c2, r2: 特殊方格的行号和列号// size = 2 ^ kvoid chessboard(int r1, int c1, int r2, int c2, int size){    if(1 == size) return;    int half_size;    int d = g_domino_num++;    half_size = size / 2;          if(r2 < r1 + half_size && c2 < c1 + half_size) //特殊方格在左上角子棋盘    {       chessboard(r1, c1, r2, c2, half_size);     }    else   // 不在此棋盘,将此棋盘右下角设为相应的骨牌号    {       board[r1 + half_size - 1][c1 + half_size - 1] = d;       chessboard(r1, c1, r1 + half_size - 1, c1 + half_size - 1, half_size);    }       if(r2 < r1 + half_size && c2 >= c1 + half_size) //特殊方格在右上角子棋盘    {       chessboard(r1, c1 + half_size, r2, c2, half_size);    }    else  // 不在此棋盘,将此棋盘左下角设为相应的骨牌号    {       board[r1 + half_size - 1][c1 + half_size] = d;       chessboard(r1, c1 + half_size, r1 + half_size - 1, c1 + half_size, half_size);    }       if(r2 >= r1 + half_size && c2 < c1 + half_size) //特殊方格在左下角子棋盘    {       chessboard(r1 + half_size, c1, r2, c2, half_size);    }    else  // 不在此棋盘,将此棋盘右上角设为相应的骨牌号    {       board[r1 + half_size][c1 + half_size - 1] = d;       chessboard(r1 + half_size, c1, r1 + half_size, c1 + half_size - 1, half_size);    }       if(r2 >= r1 + half_size && c2 >= c1 + half_size) //特殊方格在右下角子棋盘    {       chessboard(r1 + half_size, c1 + half_size, r2, c2, half_size);    }    else   // 不在此棋盘,将此棋盘左上角设为相应的骨牌号    {       board[r1 + half_size][c1 + half_size] = d;       chessboard(r1 + half_size, c1 + half_size, r1 + half_size, c1 + half_size, half_size);    }   }int main(){    int i, j;    board[2][2] = 0;int iRow,iCol;while(EOF != scanf("%d %d",&iRow,&iCol)){g_domino_num = 1;board[iRow][iCol] = 0;chessboard(0, 0, iRow, iCol, BOARD_SIZE);for(i = 0; i < BOARD_SIZE; i++){for(j = 0; j < BOARD_SIZE; j++){   printf("%-4d", board[i][j]);}printf("\n");}}getchar();}

0 0