1、在一个2k×2k个方格组成的棋盘中,恰有一个方格与其他方格不同,称该方格为一特殊方格,且称该棋盘为特殊棋盘。
如下为一个k=2的棋盘,其有2k×2k=4×4=16个不同的特殊棋盘
2、要使用图示所示的4种不同形态的L型骨牌覆盖给定的特殊棋盘上除特殊方格以外的所有方格,且任何2个L型骨牌不得重叠覆盖
例如,很容易得出在2k×2k个方格组成的特殊棋盘中,需要用(2k×2k-1)/3=(4k-1)/3个L型骨牌
k=0时,有一种覆盖方案
k>0时,采用分治策略,将2k×2k,分割成4个2k-1×2k-1个子棋盘,而特殊方格位于其中一个子棋盘,其余的子棋盘无特殊方格; 为了将这三个无特殊方格的子棋盘转化为特殊棋盘,可用一个L型骨牌覆盖这3个子棋盘的汇合处,从而将原问题转化为4个较小规模的棋盘覆盖问题,递归得调用这种分割,直到棋盘简化为1×1的棋盘
1、大棋盘:使用二维数组board[size][size]来表示这个2k×2k的棋盘,其中size=2k
2、子棋盘:子棋盘左上角下标位置tr、tc、棋盘大小s
3、特殊方格:board[dr][dc]表示,dr、dc均为特殊方格在二维数组board里面的下标
4、L型骨牌:L型骨牌在2k×2k的特殊棋盘中,所填充所需要的个数为(4k-1)/3个,对骨牌需要编号确认个数,因此需要全局变量t
/*
author:monkey
time:2020-3-26
*/
#include <stdio.h>
int chess[10][10];
int num; //L型骨牌编号
/*
tr、tc:子棋盘左上角的位置(行/列)
dr、dc:特殊方格的位置(行/列)
size:2^k^
*/
void chessBoard(int tr,int tc,int dr,int dc,int size){
if(size == 1) return;
int s = size/2;//分割棋盘成(2^k-1^)×(2^k-1^)的棋盘
int t = ++num;//L型骨牌自增
//当特殊方格位于左上角子棋盘
if(dr < tr + s&&dc < tc + s){
chessBoard(tr,tc,dr,dc,s);//有则递归调用左上子棋盘
}else{
chess[tr+s-1][tc+s-1] = t; //无则用L型骨牌填充左上子棋盘的右下角,将其变成含有特殊方格的特殊棋盘
chessBoard(tr,tc,tr+s-1,tc+s-1,s);//递归调用左上子棋盘
}
//当特殊方格位于右上角子棋盘
if(dr < tr + s && dc >= tc + s){
chessBoard(tr,tc+s,dr,dc,s); //有则递归调用右上子棋盘
}else{
chess[tr+s-1][tc+s] = t; //无则用L型骨牌填充右上子棋盘的左下角,将其变成含有特殊方格的特殊棋盘
chessBoard(tr,tc+s,tr+s-1,tc+s,s);//递归调用右上子棋盘
}
//当特殊方格位于左下角子棋盘
if(dr >= tr + s && dc < tc + s){
chessBoard(tr+s,tc,dr,dc,s);//有则递归调用左上子棋盘
}else{
chess[tr+s][tc+s-1] = t; //无则用L型骨牌填充左下子棋盘的右上角,将其变成含有特殊方格的特殊棋盘
chessBoard(tr+s,tc,tr+s,tc+s-1,s);//递归调用左下子棋盘
}
//当特殊方格位于右下角子棋盘
if(dr >=tr + s&&dc >= tc + s){
chessBoard(tr+s,tc+s,dr,dc,s);//有则递归调用右下子棋盘
}else{
chess[tr+s][tc+s] = t; //无则用L型骨牌填充右下子棋盘的左上角,将其变成含有特殊方格的特殊棋盘
chessBoard(tr+s,tc+s,tr+s,tc+s,s);//递归调用右下子棋盘
}
}
int main(){
int dr,dc,size;
while(true){
printf("请输入棋盘大小以及特殊方格的位置:");
scanf("%d %d %d",&size,&dr,&dc);
if(size == 0)
break;
//初始化
chess[dr][dc] = 1;
num = 1;
chessBoard(0,0,dr,dc,size);
printf("填充完后的棋盘显示:\n");
for(int i = 0;i < size;i++){
for(int j = 0;j < size;j++){
printf("%d",chess[i][j]);
printf(" ");
}
printf("\n");
}
}
return 0;
}
package main
import "fmt"
func HuaFen(n int,m int)int{
if n < 1||m < 1{
return 0
}else if n == 1||m == 1 {
return 1
}else if n < m {
return HuaFen(n,n)
}else if n == m {
return HuaFen(n,m-1)+1
}else{
return HuaFen(n,m-1)+HuaFen(n-m,m)
}
}
func main() {
var num int
for {
fmt.Print("输入需要划分的数字:")
fmt.Scanf("%d",&num)
if num == 0{
break
}
res := HuaFen(num,num)
fmt.Printf("数字%d划分的结果有%d种\n",num,res)
}
}