您的位置:首页 > 其它

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

2015-08-19 09:16 495 查看
/*
棋盘覆盖:
有一个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 3
2 1 1 3
4 1 0 5
4 4 5 5
相同数字的为同一骨牌。

本质:
棋盘每次分成4块子棋盘,递归处理含特殊方格的子棋盘,直到这个子棋盘只有一个格子为止。
其余三个不含特殊格的子棋盘中,将这个子棋盘的位置设为骨牌号(?),将这个无特殊的子棋盘
转换为右特殊方格的子棋盘。

输入:
0 1(左上角测试)
1 3(右上角测试)
3 0(左下角测试)
2 2 (右下角测试)

输出:
2 0 3 3
2 2 1 3
4 1 1 5
4 4 5 5

2 2 3 3
2 1 3 0
4 1 1 5
4 4 5 5

2 2 3 3
2 1 1 3
4 4 1 5
0 4 5 5

2 2 3 3
2 1 1 3
4 1 0 5
4 4 5 5

*/

#include <stdio.h>

#define BOARD_SIZE 4
int board[BOARD_SIZE][BOARD_SIZE];
int g_domino_num;

// c1, r1: 棋盘左上角的行号和列号
// c2, r2: 特殊方格的行号和列号
// size = 2 ^ k
void 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();
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: