实验目的
了解和运用递归与分治算法解决实际问题。
实验内容
残缺棋盘是一个有2k×2k(k≥1)个方格的棋盘,其中恰有一个方格残缺。如图给出k=1时各种可能的残缺棋盘,其中残缺的方格用阴影表示。残缺棋盘问题就是要用这四种三格板覆盖更大的残缺棋盘。在此覆盖中要求:
1)两个三格板不能重叠
2)三格板不能覆盖残缺方格,但必须覆盖其他所有的方格。
小格子数(2k×2k -1)三格板中小格子数3。所以所需要的三格板总数为(2k×2k
-1 )/3。例如,一个44的残缺棋盘2k2k。以k=2时的问题为例,用二分法进行分解,得到的四个k=1的棋盘。但要注意这四个棋盘,并不都是与原问题相似且独立的子问题。
算法分析
从以上例子还可以发现当残缺方格在第1个子棋盘,用①号三格板覆盖其余三个子棋盘的交界方格,可以使另外三个子棋盘转化为独立子问题;当残缺方格在第2个子棋盘时,则首先用②号三格板进行棋盘覆盖当残缺方格在第3个子棋盘时,则首先用③号三格板进行棋盘覆盖当残缺方格在第4个子棋盘时,则首先用④号三格板进行棋盘覆盖,这样就使另外三个子棋盘转化为独立子问题。
实验步骤
#include<iostream>
using namespace std;
#include<stdio.h>
int amount=0,board[100][100];//规定棋盘大小
void cover(int tr,int tc,int dr,int dc,int size)//用三格板覆盖棋盘
{
int s,t;
if(size<2)return ;
amount+=1;
t=amount;
s=size/2;
if(dr<tr+s&&dc<tc+s)//残缺棋盘位于左上
{
cover(tr,tc,dr,dc,s);
board[tr+s-1][tc+s]=t;
board[tr+s][tc+s-1]=t;
board[tr+s][tc+s]=t;
cover(tr,tc+s,tr+s-1,tc+s,s);
cover(tr+s,tc,tr+s,tc+s-1,s);
cover(tr+s,tc+s,tr+s,tc+s,s);
}
else if(dr<tr+s&&dc>=tc+s)//残缺方格位于右上
{
cover(tr,tc+s,dr,dc,s);
board[tr+s-1][tc+s-1]=t;
board[tr+s][tc+s-1]=t;
board[tr+s][tc+s]=t;
cover(tr,tc,tr+s-1,tc+s-1,s);
cover(tr+s,tc,tr+s,tc+s-1,s);
cover(tr+s,tc+s,tr+s,tc+s,s);
}
else if(dr>=tr+s&&dc<tc+s)//残缺方格位于左下
{
cover(tr+s,tc,dr,dc,s);//覆盖三号版
board[tr+s-1][tc+s-1]=t;
board[tr+s-1][tc+s]=t;
board[tr+s][tc+s]=t;
cover(tr,tc,tr+s-1,tc+s-1,s);//覆盖其余部分
cover(tr,tc+s,tr+s-1,tc+s,s);
cover(tr+s,tc+s,tr+s,tc+s,s);
}
else if(dr>=tr+s&&dc>=tc+s)//残缺方格位于右下
{
cover(tr+s,tc+s,dr,dc,s);
board[tr+s-1][tc+s-1]=t;//覆盖四号板
board[tr+s-1][tc+s]=t;
board[tr+s][tc+s-1]=t;
cover(tr,tc,tr+s-1,tc+s-1,s);//覆盖其余部分
cover(tr,tc+s,tr+s-1,tc+s,s);
cover(tr+s,tc,tr+s,tc+s-1,s);
}
}
void outputboard(int size)//输出棋盘
{
int i,j;
for(i=0;i<size;i++)
{
for(j=0;j<size;j++)
printf("%d\t",board[i][j]);
cout<<endl;
}
}
int main()
{
int size=1,x,y,i,j,k;
printf("输入K的值:");
scanf("%d",&k);
for(i=1;i<=k;i++)
size*=2;
printf("输入残缺棋盘中残缺的位置:");
cin>>x>>y;
cover(0,0,x,y,size);
outputboard(size);
return 0;
}