题目描述
如下的10个格子,填入0~9的数字。要求:连续的两个数字不能相邻。
(左右、上下、对角都算相邻)一共有多少种可能的填数方案?
输出
请填写表示方案数目的整数。
这道题目给了我们十个数,然后让我们将空格填满并且保证连续的两个数不相邻就可以了
法一:
dfs:
将数字0到9向后推移两位,变为2到11, 这样做可以避免0和1这连个连续数,毕竟我已经将这个5*5的数组周围填满了0.
还有一个地方需要注意,我们在dfs每一层的时候,怎么通过当前层数u变为对应二维数组下的坐标呢?
令我们的层数从1开始遍历,那么每一层的层数u对应的下标就可以表示为:
x = u / 4 + 1;
y = u - u / 4 * 4 + 1;
我们dfs 的大体思路是这样的,遍历每一层,并且在每一层都要判断当前的这个位置的数是否合法。
#include <iostream>
#include <cstring>
#include <cmath>
using namespace std;
int res;
int g[5][6];
bool st[13];
bool check(int x, int y, int t){
int dx[8] = {0, -1, 0, 1, -1, -1, 1, 1};//偏移量
int dy[8] = {-1, 0, 1, 0, -1, 1, -1, 1};//偏移量
for (int i = 0; i < 8; i ++ ){
int a = x + dx[i], b = y + dy[i];
if (abs(g[a][b] - t ) == 1) return false;
}
return true;
}
void dfs(int u){
if (u == 11) {
res ++;
return;
}
for (int i = 2; i <= 11; i ++ ){
if (!st[i]){
int x=1+u/4;
int y=u-u/4*4+1;
if (check(x, y, i)){
st[i] = true;
g[x][y] = i;
dfs(u + 1);
g[x][y] = 0;
st[i] = false;
}
}
}
}
int main(){
dfs(1);
cout << res << endl;
return 0;
}
暴力枚举
暴力枚举所有顺序,然后依次判断是否合法
#include <iostream>
#include <cstring>
#include <algorithm>
using namespace std;
int res;
int a[10] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9};
bool st[10];
bool check(){
if (
abs(a[0] - a[1] ) == 1 ||
abs(a[0] - a[3] ) == 1 ||
abs(a[0] - a[4] ) == 1 ||
abs(a[0] - a[5] ) == 1 ||
abs(a[1] - a[4] ) == 1 ||
abs(a[1] - a[5] ) == 1 ||
abs(a[1] - a[6] ) == 1 ||
abs(a[1] - a[2] ) == 1 ||
abs(a[2] - a[5] ) == 1 ||
abs(a[2] - a[6] ) == 1 ||
abs(a[3] - a[7] ) == 1 ||
abs(a[3] - a[8] ) == 1 ||
abs(a[3] - a[4] ) == 1 ||
abs(a[4] - a[7] ) == 1 ||
abs(a[4] - a[8] ) == 1 ||
abs(a[4] - a[9] ) == 1 ||
abs(a[4] - a[5] ) == 1 ||
abs(a[5] - a[8] ) == 1 ||
abs(a[5] - a[9] ) == 1 ||
abs(a[5] - a[6] ) == 1 ||
abs(a[6] - a[9] ) == 1 ||
abs(a[7] - a[8] ) == 1 ||
abs(a[8] - a[9] ) == 1
){
return false;
}
return true;
}
void dfs(int u){
if (u == 10) {
if (check()) res ++;
return;
}
for (int i = 0; i < 10; i ++ ){
if (!st[i]){
st[i] = true;
a[u] = i;
dfs(u + 1);
st[i] = false;
}
}
}
int main(){
dfs(0);
cout << res << endl;
return 0;
}
也可写为
#include <iostream>
#include <cstring>
#include <algorithm>
using namespace std;
int res;
int a[10] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9};
bool check(){
if (
abs(a[0] - a[1] ) == 1 ||
abs(a[0] - a[3] ) == 1 ||
abs(a[0] - a[4] ) == 1 ||
abs(a[0] - a[5] ) == 1 ||
abs(a[1] - a[4] ) == 1 ||
abs(a[1] - a[5] ) == 1 ||
abs(a[1] - a[6] ) == 1 ||
abs(a[1] - a[2] ) == 1 ||
abs(a[2] - a[5] ) == 1 ||
abs(a[2] - a[6] ) == 1 ||
abs(a[3] - a[7] ) == 1 ||
abs(a[3] - a[8] ) == 1 ||
abs(a[3] - a[4] ) == 1 ||
abs(a[4] - a[7] ) == 1 ||
abs(a[4] - a[8] ) == 1 ||
abs(a[4] - a[9] ) == 1 ||
abs(a[4] - a[5] ) == 1 ||
abs(a[5] - a[8] ) == 1 ||
abs(a[5] - a[9] ) == 1 ||
abs(a[5] - a[6] ) == 1 ||
abs(a[6] - a[9] ) == 1 ||
abs(a[7] - a[8] ) == 1 ||
abs(a[8] - a[9] ) == 1
){
return false;
}
return true;
}
void dfs(int u){
if (u == 10) {
if (check()) res ++;
return;
}
for (int i = u; i < 10; i ++ ){
swap(a[i], a[u]);
dfs(u + 1);
swap(a[i], a[u]);
}
}
int main(){
dfs(0);
cout << res << endl;
return 0;
}
也可以用next_permutation()函数来枚举
int main(){
do{
if (check()) res ++;
}
while (next_permutation(a, a + 10));
cout << res << endl;
return 0;
}