方格填数
如下的10个格子
填入0~9的数字。要求:连续的两个数字不能相邻。
(左右、上下、对角都算相邻)
一共有多少种可能的填数方案?
请填写表示方案数目的整数。
注意:你提交的应该是一个整数,不要填写任何多余的内容或说明性文字。
解析
C++题解
方法一
将该10个格子按顺序拉成一个一维数组,然后将十个数字填进去(全排列),填完之后进行判断即可。
#include <bits/stdc++.h>
using namespace std;
int a[11], Ans;
int calc(int x, int y) {
return abs(a[x]-a[y]);
}
bool check() {
if(calc(0, 1) == 1) return false;
if(calc(0, 3) == 1) return false;
if(calc(0, 4) == 1) return false;
if(calc(0, 5) == 1) return false;
if(calc(1, 2) == 1) return false;
if(calc(1, 4) == 1) return false;
if(calc(1, 5) == 1) return false;
if(calc(1, 6) == 1) return false;
if(calc(2, 5) == 1) return false;
if(calc(2, 6) == 1) return false;
if(calc(3, 4) == 1) return false;
if(calc(3, 7) == 1) return false;
if(calc(3, 8) == 1) return false;
if(calc(4, 5) == 1) return false;
if(calc(4, 7) == 1) return false;
if(calc(4, 8) == 1) return false;
if(calc(4, 9) == 1) return false;
if(calc(5, 6) == 1) return false;
if(calc(5, 8) == 1) return false;
if(calc(5, 9) == 1) return false;
if(calc(6, 9) == 1) return false;
if(calc(7, 8) == 1) return false;
if(calc(8, 9) == 1) return false;
return true;
}
void dfs(int pos) {
if(pos == 10) {
if(check()) Ans ++;
return ;
}
for(int i=pos; i<10; ++i) {
int t = a[pos]; a[pos] = a[i]; a[i] = t;
dfs(pos+1);
t = a[pos]; a[pos] = a[i]; a[i] = t;
}
}
int main() {
for(int i=0; i<=10; ++i)
a[i] = i;
dfs(0);
printf("%d\n", Ans);
return 0;
}
方法二
在原图的基础上加一圈,然后判断。这个方法的check函数较为简洁。初始化可以不是-10,只要不与0-9相差±1即可。
#include <bits/stdc++.h>
using namespace std;
int Map[5][6], Ans;
bool vis[10];
bool check(int x, int y) {
for(int i=x-1; i<=x+1; ++i) {
for(int j=y-1; j<=y+1; ++j) {
if(abs(Map[x][y]-Map[i][j]) == 1)
return false;
}
}
return true;
}
void dfs(int x, int y) {
if(x==3 && y==4) {
Ans++;
return ;
}
for(int i=0; i<10; ++i) {
if(vis[i]) continue; //这个数字用了
Map[x][y] = i; // 先放着
if(!check(x, y)) {
Map[x][y] = -10; //
continue; //放下不符规则
}
vis[i] = true;
if(y == 4)
dfs(x+1, 1); // 换行
else dfs(x, y+1); // 右边的格子
Map[x][y] = -10; // 回溯
vis[i] = false;
}
}
int main() {
for(int i=0; i<10; ++i) vis[i] = false;
for(int i=0; i<5; ++i) // 外面加一圈
for(int j=0; j<6; ++j)
Map[i][j] = -10;
dfs(1, 2); //第一个填数的格子是(1,2)
printf("%d\n", Ans);
return 0;
}
如图:
Java题解
public class _06方格填数 {
public static void main(String[] args) {
dfs(0);
System.out.println(ans);
}
static int[] a = new int[] {0,1,2,3,4,5,6,7,8,9};
static int ans=0;
static void dfs(int m) {
if(m>=10) {
if(a[0]==a[1]-1 || a[0]==a[1]+1 || a[0]==a[4]-1 || a[0]==a[4]+1 || a[0]==a[3]-1 || a[0]==a[3]+1 || a[0]==a[5]-1 || a[0]==a[5]+1)
return;
if(a[1]==a[2]-1 || a[1]==a[2]+1 || a[1]==a[5]-1 || a[1]==a[5]+1 || a[1]==a[4]-1 || a[1]==a[4]+1 || a[1]==a[6]-1 || a[1]==a[6]+1)
return;
if(a[2]==a[6]-1 || a[2]==a[6]+1 || a[2]==a[5]-1 || a[2]==a[5]+1)
return;
if(a[3]==a[4]-1 || a[3]==a[4]+1 || a[3]==a[7]-1 || a[3]==a[7]+1 || a[3]==a[8]-1 || a[3]==a[8]+1)
return;
if(a[4]==a[5]-1 || a[4]==a[5]+1 || a[4]==a[8]-1 || a[4]==a[8]+1 || a[4]==a[7]-1 || a[4]==a[7]+1 || a[4]==a[9]-1 || a[4]==a[9]+1)
return;
if(a[5]==a[6]-1 || a[5]==a[6]+1 || a[5]==a[8]-1 || a[5]==a[8]+1 || a[5]==a[9]-1 || a[5]==a[9]+1)
return;
if(a[6]==a[9]-1 || a[6]==a[9]+1 || a[7]==a[8]-1 || a[7]==a[8]+1 || a[8]==a[9]-1 || a[8]==a[9]+1)
return;
for(int i=0;i<=9;i++)
System.out.print(a[i]+" ");
System.out.println();
ans++;
return;
}
for(int i=m;i<10;i++) {
swap(m,i);
dfs(m+1);
swap(m,i);
}
}
static void swap(int i,int j) {
int t = a[i];
a[i] = a[j];
a[j] = t;
}
}