自己做完之后对比了下网上的解题思路都是归纳出递归式直接求值,这里给出我的一个搜索方法。 思路:
- 求f(n)使得f(n)能完美覆盖棋盘
- 棋盘总的格子数目是3*n,因此如果n是奇数,一定不会被完美覆盖
- 我们假定一直先横向摆放多米诺古牌,如果摆放过那么对他进行标记,横向的就是标记(x,y)与(x+1,y),然后找下一个可能摆放的位置,如果能找到那么继续标记;如果找不到,那么返回到纵向搜索,同时清除这一步之前的所有标记(只需要每次调用递归函数后清除就行了),然后继续搜索;如果还没搜索到那么继续继续上面两个步骤。
- 伪代码f(x,y) = f(x+2,y) + f(x,y+1)(横向和纵向搜索之和)
- 退出条件:下一个搜索点的y==3(因为我们始终先横向搜索)
- 对于横向,只有横向占据的两点(x,y)和(x+1,y)的横纵坐标都分别不大于col与row,并且这两点之前没有没标记过,那么我们继续搜索;否则此次搜索不成立,直接返回;同理对于纵向也是一样
#include <iostream>
#include <vector>
using namespace std;
const int ROW = 3;
struct point{
int x;
int y;
};
point nextPoint(char **a,int x, int y,int col,int direct){
if(direct == 0){ //横向
x = x+2;
}else{ //纵向
x += 1;
}
if(x>col-1){
x = 0;
y = y+1;
if(y == ROW){
point p = {-1,-1};
return p;
}
}
if(a[y][x] == '_' || a[y][x] == '|'){
return nextPoint(a, x, y,col, 1);
}else{
point tmp = {x,y};
return tmp;
}
}
int total;
void printArr(char **a,int row,int col){
for(int i=0;i<row;i++){
for(int j=0;j<col;j++){
cout<<a[i][j];
}
cout<<endl;
}
cout<<"next line"<<endl;
}
void func(char **a,int n_x, int n_y, int row, int col,int direc){
if(n_x == -1){
total++;
printArr(a, row, col);
return;
}
//1.水平方向,标记
if(direc==0){
if(n_y<row && n_x<col && n_x+1<col && a[n_y][n_x] == ' ' && a[n_y][n_x+1] == ' '){
a[n_y][n_x] = '_';
a[n_y][n_x+1] = '_';
point p = nextPoint(a, n_x, n_y, col,-1);
func(a, p.x, p.y, row,col,-1);
a[n_y][n_x] = ' ';
a[n_y][n_x+1] = ' ';
}else{
return;
}
}
//竖直方向
if(direc == 1){
if(n_x< col && n_y <row && n_y+1<row && a[n_y+1][n_x] ==' ' && a[n_y][n_x] == ' '){
a[n_y+1][n_x] = '|';
a[n_y][n_x] = '|';
point p = nextPoint(a, n_x, n_y, col, direc);
func(a, p.x, p.y, row,col,-1);
a[n_y+1][n_x] = ' ';
a[n_y][n_x] = ' ';
}else{
return;
}
}
if(direc == -1){
func(a, n_x, n_y, row, col,0);
func(a, n_x, n_y, row, col,1);
}
}
int main(){
int COL;
cin>>COL;
if(COL%2){
cout<<"不能完美覆盖"<<endl;
return 0;
}
char **a = new char*[ROW];
for(int i=0;i<ROW;i++){
a[i] = new char[COL+1];
}
//最外层加圈
for(int i=0;i<ROW;i++){
for(int j=0;j<COL;j++){
a[i][j] = ' ';
}
}
//初始方向设置为-1,然后再函数内横向0,纵向1搜索
func(a, 0, 0, ROW, COL,-1);
cout<<"total"<<total<<endl;
}