一道很有趣的递归与分治的题目。
关键搞好各个位置的下标关系,以及将整个图分为四部分,如果特殊点不在此部分,则将整个图中间的三个方块标记为特殊点。注释很详细。
画了一张图(主要是还得交作业,不然才不画呢,哈哈哈哈):
先贴上递归实现的代码:
/*
棋盘覆盖的递归算法
棋盘大小为size(2^k)*size大小
*/
#include<iostream>
const int Max=16;
int map[Max][Max];
using namespace std;
int tile;
void ChessBoard(int lr,int lc,int dr,int dc,int size)
{
if(size==1)return;
//L型骨牌号
int cnt=++tile;
int s=size/2;
//处理左上角部分
if(dr<lr+s&&dc<lc+s)//如果特殊方格在左上角
{
ChessBoard(lr,lc,dr,dc,s);
}
else //骨牌覆盖到右下角
{
map[lr+s-1][lc+s-1]=cnt;
ChessBoard(lr,lc,lr+s-1,lc+s-1,s);
}
//处理右上角部分
if(dr<lr+s&&dc>=lc+s)
{
ChessBoard(lr,lc+s,dr,dc,s);
}
else//覆盖到左下角
{
map[lr+s-1][lc+s]=cnt;
ChessBoard(lr,lc+s,lr+s-1,lc+s,s);
}
//处理左下角部分
if(dr>=lr+s&&dc<lc+s)
{
ChessBoard(lr+s,lc,dr,dc,s);
}
else//覆盖到右上角
{
map[lr+s][lc+s-1]=cnt;
ChessBoard(lr+s,lc,lr+s,lc+s-1,s);
}
//处理右下角部分
if(dr>=lr+s&&dc>=lc+s)
{
ChessBoard(lr+s,lc+s,dr,dc,s);
}
else//覆盖到左上角
{
map[lr+s][lc+s]=cnt;
ChessBoard(lr+s,lc+s,lr+s,lc+s,s);
}
}
void display()
{
for(int i=0;i<Max;i++)
{
for(int j=0;j<Max;j++)
{
// cout<<map[i][j]<<" ";
printf("%-2d ",map[i][j]);
}
cout<<endl;
}
}
int main()
{
ChessBoard(0,0,0,0,Max);
display();
return 0;
}
栈 模拟实现:敲得晕晕的.........还是递归写起来舒服优美....
#include<iostream>
#include<stack>
using namespace std;
const int Max=8;
int map[Max][Max];
int cnt=1;
struct node{
int sx,sy; //每一小块的起始坐标
int dx,dy; //特殊方格的坐标
int size; //小块的大小初始size=2^k;
int num; //用于标记骨牌号
};
stack<node> s;
void init()
{
node p;
p.dx=p.dy=p.sx=p.sy=0;
p.size=Max;
p.num=cnt++;
p.size=Max;
s.push(p);
}
void solve()
{
while(!s.empty())
{
node tmp=s.top();
s.pop();
//如果每一部分只有一块
if(tmp.size==1)
{
cnt--;
continue;
}
//被分割后的块大小
int sz=tmp.size/2;
//下一个入栈结点值得初始化
node next=tmp;
next.size=tmp.size/2;
next.num=cnt++;
//处理左上角部分
if(tmp.dx<tmp.sx+sz&&tmp.dy<tmp.sy+sz)
{
next.sx=tmp.sx;
next.sy=tmp.sy;
next.dx=tmp.dx;
next.dy=tmp.dy;
s.push(next);
}
else
{
map[tmp.sx+sz-1][tmp.sy+sz-1]=tmp.num;
// map[tmp.sy+sz-1][tmp.sx+sz-1]=tmp.num;
next.dx=tmp.sx+sz-1;
next.dy=tmp.sy+sz-1;
s.push(next);
}
next.num=cnt++;
//处理右上角部分
if(tmp.dx<tmp.sx+sz&&tmp.dy>=tmp.sy+sz)
{
next.sx=tmp.sx;
next.sy=tmp.sy+sz;
next.dx=tmp.dx;
next.dy=tmp.dy;
s.push(next);
}
else
{
map[tmp.sx+sz-1][tmp.sy+sz]=tmp.num;
// map[tmp.sy+sz][tmp.sx+sz-1]=tmp.num;
next.dx=tmp.sx+sz-1;
next.dy=tmp.sy+sz;
next.sx=tmp.sx;
next.sy=tmp.sy+sz;
s.push(next);
}
next.num=cnt++;
//处理左下角的部分
if(tmp.dx>=tmp.sx+sz&&tmp.dy<tmp.sy+sz)
{
next.sx=tmp.sx+sz;
next.sy=tmp.sy;
next.dx=tmp.dx;
next.dy=tmp.dy;
s.push(next);
}
else
{
map[tmp.sx+sz][tmp.sy+sz-1]=tmp.num;
// map[tmp.sy+sz-1][tmp.sx+sz]=tmp.num;
next.sx=tmp.sx+sz;
next.sy=tmp.sy;
next.dx=tmp.sx+sz;
next.dy=tmp.sy+sz-1;
s.push(next);
}
next.num=cnt++;
//处理右下角
if(tmp.dx>=tmp.sx+sz&&tmp.dy>=tmp.sy+sz)
{
next.sx=tmp.sx+sz;
next.sy=tmp.sy+sz;
next.dx=tmp.sx;
next.dy=tmp.sy;
s.push(next);
}
else
{
map[tmp.sx+sz][tmp.sy+sz]=tmp.num;
// map[tmp.sy+sz][tmp.sx+sz]=tmp.num;
next.sx=tmp.sx+sz;
next.sy=tmp.sy+sz;
next.dx=tmp.sx+sz;
next.dy=tmp.sy+sz;
s.push(next);
}
}
}
void display()
{
for(int i=0;i<Max;i++)
{
for(int j=0;j<Max;j++)
{
printf("%-3d ",map[i][j]);
}
cout<<endl;
}
}
int main()
{
init();
solve();
display();
return 0;
}
队列实现:和栈实现相比改了一行代码......
#include<iostream>
#include<queue>
using namespace std;
const int Max=8;
int map[Max][Max];
int cnt=1;
struct node{
int sx,sy; //每一小块的起始坐标
int dx,dy; //特殊方格的坐标
int size; //小块的大小初始size=2^k;
int num; //用于标记骨牌号
};
queue<node> s;
void init()
{
node p;
p.dx=p.dy=p.sx=p.sy=0;
p.size=Max;
p.num=cnt++;
p.size=Max;
s.push(p);
}
void solve()
{
while(!s.empty())
{
node tmp=s.front();
s.pop();
//如果每一部分只有一块
if(tmp.size==1)
{
cnt--;
continue;
}
//被分割后的块大小
int sz=tmp.size/2;
//下一个入栈结点值得初始化
node next=tmp;
next.size=tmp.size/2;
next.num=cnt++;
//处理左上角部分
if(tmp.dx<tmp.sx+sz&&tmp.dy<tmp.sy+sz)
{
next.sx=tmp.sx;
next.sy=tmp.sy;
next.dx=tmp.dx;
next.dy=tmp.dy;
s.push(next);
}
else
{
map[tmp.sx+sz-1][tmp.sy+sz-1]=tmp.num;
// map[tmp.sy+sz-1][tmp.sx+sz-1]=tmp.num;
next.dx=tmp.sx+sz-1;
next.dy=tmp.sy+sz-1;
s.push(next);
}
next.num=cnt++;
//处理右上角部分
if(tmp.dx<tmp.sx+sz&&tmp.dy>=tmp.sy+sz)
{
next.sx=tmp.sx;
next.sy=tmp.sy+sz;
next.dx=tmp.dx;
next.dy=tmp.dy;
s.push(next);
}
else
{
map[tmp.sx+sz-1][tmp.sy+sz]=tmp.num;
// map[tmp.sy+sz][tmp.sx+sz-1]=tmp.num;
next.dx=tmp.sx+sz-1;
next.dy=tmp.sy+sz;
next.sx=tmp.sx;
next.sy=tmp.sy+sz;
s.push(next);
}
next.num=cnt++;
//处理左下角的部分
if(tmp.dx>=tmp.sx+sz&&tmp.dy<tmp.sy+sz)
{
next.sx=tmp.sx+sz;
next.sy=tmp.sy;
next.dx=tmp.dx;
next.dy=tmp.dy;
s.push(next);
}
else
{
map[tmp.sx+sz][tmp.sy+sz-1]=tmp.num;
// map[tmp.sy+sz-1][tmp.sx+sz]=tmp.num;
next.sx=tmp.sx+sz;
next.sy=tmp.sy;
next.dx=tmp.sx+sz;
next.dy=tmp.sy+sz-1;
s.push(next);
}
next.num=cnt++;
//处理右下角
if(tmp.dx>=tmp.sx+sz&&tmp.dy>=tmp.sy+sz)
{
next.sx=tmp.sx+sz;
next.sy=tmp.sy+sz;
next.dx=tmp.sx;
next.dy=tmp.sy;
s.push(next);
}
else
{
map[tmp.sx+sz][tmp.sy+sz]=tmp.num;
// map[tmp.sy+sz][tmp.sx+sz]=tmp.num;
next.sx=tmp.sx+sz;
next.sy=tmp.sy+sz;
next.dx=tmp.sx+sz;
next.dy=tmp.sy+sz;
s.push(next);
}
}
}
void display()
{
for(int i=0;i<Max;i++)
{
for(int j=0;j<Max;j++)
{
printf("%-3d ",map[i][j]);
}
cout<<endl;
}
}
int main()
{
init();
solve();
display();
return 0;
}