问题:方格填数
如下的10个格子
±-±-±-+
| | | |
±-±-±-±-+
| | | | |
±-±-±-±-+
| | | |
±-±-±-+
填入0~9的数字。要求:连续的两个数字不能相邻。
(左右、上下、对角都算相邻)
一共有多少种可能的填数方案?
请填写表示方案数目的整数。
注意:你提交的应该是一个整数,不要填写任何多余的内容或说明性文字。
思考:方格填数问题与四皇后问题类似 ;(运用回溯法的思想)
一,可以理解为有一个三行四列的数组;
(当然,题目中没有格子的地方可以理解为该位置不能够放置数字)
二,运用回溯法思想:
1,设置一个三行四列的数组,给他们初始化的时候避免出现题中0到9产生混淆,其中不能存放数字的地方与其
余初始化区别开,方便以后条件判断
2,先考虑第一列的三个位置,然后第一列的每一个位置在延申到第二列,这样就遍历了所有的情况。
3,数字不能重复我设置了一个能存放十个数字的数组,每次用后设置标志位1,然后遍历完所有表格一次清零;
4,不能相邻问题我用了一个方法,通过对数组左右,上下,对角线分别进行条件判断,当然,不能放置数字的;
位置初始化较大,不会与其余空格有连续情况影响;
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
int sum=0;
int h[10]={0};
int m(int (*s)[4],int i,int j){ //判断该位置是否可以放置数据
for(i=0;i<3;i++){
for(j=0;j<4;j++){
if(s[i][j]==100){
return 1;
}
else{
return 0;
}
}
}
}
int isplace(int a[3][4],int i,int j){ //断空格的当前位置能否放置该数据
if(j>=1){
if(abs(a[i][j]-a[i][j-1])==1){ //水平左边
return 0;
}
}
if(j<=2){
if(abs(a[i][j]-a[i][j+1]==1)){ //水平右边
return 0;
}
}
if(i>=1){ //垂直上端
if(abs(a[i][j]-a[i-1][j]==1)){
return 0;
}
}
if(i<=1){ //垂直下端
if(abs(a[i][j]-a[i+1][j]==1)){
return 0;
}
}
if((i>=1)&&(j>=1)){ //对角线左上
if(abs(a[i][j]-a[i-1][j-1]==1)){
return 0;
}
}
if((i<=1)&&(j<=2)){ //对角线右下
if(abs(a[i][j]-a[i+1][j+1]==1)){
return 0;
}
}
if((i>=1)&&(j<=2)){ //对角线右上
if(abs(a[i][j]-a[i-1][j+1]==1)){
return 0;
}
}
if((i<=1)&&(j>=1)){ //对角线左下
if(abs(a[i][j]-a[i+1][j-1]==1)){
return 0;
}
}
return 1;
}
void dfs(int s[3][4],int k){ //三行四列
int i,j,l;
int f,n;
if((i==2)&&(k==3)){ //遍历完题中给出方格布局的最后一个位置,递归出口
sum++;
for(j=0;j<=9;j++){ //第一次所有情况遍历完数字使用记录清零;
h[j]=0;
}
for(f=0;f<3;f++){ //遍历完一次再次初始化
for(n=0;n<4;n++){
s[i][j]=100;
}
}
s[0][0]=99;
s[2][3]=99;
return ; //一次遍历结束
}
for(i=0;i<3;i++){ //遍历第一列的每个元素
if(m(s,i,k)){
for(l=0;l<=9;l++){ //保证不重复也是个问题 :这里需要一个存放0到9是个元素的数组
s[i][k]=l;
if(isplace(s,i,k)&&h[l]==0) h[l]=1; break;
}
}
dfs(s,k+1);
}
}
int main(int argc, char *argv[]) {
int a[3][4];
int i,j,k=0;
for(i=0;i<3;i++){
for(j=0;j<4;j++){
a[i][j]=100;
}
}
a[0][0]=99;
a[2][3]=99; //以上两个位置表示不可以放置数据
dfs(a,0);
printf("%d",sum);
return 0;
}