题目描述:
如下的10个格子
填入0~9的数字。要求:连续的两个数字不能相邻。
(左右、上下、对角都算相邻)
(左右、上下、对角都算相邻)
一共有多少种可能的填数方案?
请填写表示方案数目的整数。
注意:你提交的应该是一个整数,不要填写任何多余的内容或说明性文字。
解题思路:
这是一道考察递归回溯的题目。首先需要定义一个Map[][]的二维数组来存放数值,一个标记数组判断该数值是否使用。第一个方格为递归的起点,可以放0-9十种情况,所以递归的方法也就是十种。递归函数传入的参数是填入数值的个数。当填入的数字大于十个的时候,就停止递归,然后填数的种类加一;当参数小于等于十次的时候,就需要判断0-9个数值中的一个是否可以继续递归下去,如果可以,对该数值进行标记,并把该数值存到对应的Map[][]数组里面,最后递归完以后回溯到调用递归之前的状态。
这里要注意,Map[][]里面的值一开始都要赋值11(小于等于-2,大于等于11),这样0-9所有的数都不能与之相邻。
代码如下:
#include<iostream>
#include<cstdio>
#include<cstring>
#include<string>
#include<algorithm>
using namespace std;
int a[10];
int Map[5][6];//
int ans;
int dir[8][2]= {1,0,-1,0,0,1,0,-1,1,1,1,-1,-1,1,-1,-1};
bool judge(int num,int t)//判断该数值是否可以存入Map[][]数组中
{
int temp=1;
int x=num/4+1;//表示横坐标
int y=num%4+1;//表示纵坐标
for(int i=0; i<8; i++)//八个方向
{
int x1=x+dir[i][0];
int y1=y+dir[i][1];
if(Map[x][y]==Map[x1][y1]+1||Map[x][y]==Map[x1][y1]-1)//判断数值是否相邻
{
temp=0;
break;
}
}
if(a[t]==1)//判断是否被标记
temp=0;
if(temp==0)
return false;
else
return true;
}
void dfs(int n)
{
n++;
if(n==11)//如果填入的数值个数大于10就停止递归,并且种类加一
{
ans++;
return ;
}
for(int i=0; i<=9; i++)
{
Map[n/4+1][n%4+1]=i;
if(judge(n,i))//符合条件进行递归,不符合Map[][]还原成以前的状态
{
a[i]=1;
dfs(n);
Map[n/4+1][n%4+1]=11;//回溯Map
a[i]=0;//回溯标记数组a
}
else
Map[n/4+1][n%4+1]=11;
}
}
int main()
{
memset(a,0,sizeof(a));
ans=0;
for(int i=0; i<=4; i++)
{
for(int j=0; j<=5; j++)
Map[i][j]=11;
}
for(int i=0; i<=9; i++)//起点的10种可能
{
a[i]=1;
Map[1][2]=i;
dfs(1);
Map[1][2]=11;
a[i]=0;
}
cout<<ans<<endl;
return 0;
}