我们先把全排列的板子写上,然后再来思考check()部分怎么样。板子有两个,一个是库的板子,一个是自己用数组模拟:
#include <iostream>
using namespace std;
int a[]={0,1,2,3,4,5,6,7,8,9};
int ans;
bool check()
{
}
void f(int k)
{
if(k==10)
{
if(check())
{
ans++;
}
}
for(int i=k;i<10;i++)
{
{int t=a[k];a[k]=a[i];a[i]=t;}
f(k+1);
{int t=a[k];a[k]=a[i];a[i]=t;}
}
}
int main()
{
f(0);
cout<<ans;
return 0;
}
#include<bits/stdc++.h>using namespace std;
int ans;
bool check()
{
}
int main()
{
int a[20]={1,2,3,4,6,7,8,9};
do
{
if(check())ans++;
}while(next_permutaation(a,a+n));
cout<<ans<<endl;
return 0;
}
接下来我们来写check()部分:
题目说了连续的两个数不能相邻,上下左右和对角都算相邻。
因此 a[0]不能和a[1] a[3] a[4] a[5] 存在连续关系
a[1]不能和a[0] a[2] a[4] a[5] a[6]存在连续关系,
a[2]不能和a[1] a[5] a[6]存在连续关系
a[3]不能和a[4] a[7]存在连续关系
a[4]不能和1a[0] a[1] a[3] a[5] a[7] a[8] a[9]存在连续关系
a[5]不能和a[0] a[1] a[2] a[6] a[8] a[9]存在连续关系
a[6]不能和a[2]] a[5]存在连续关系
a[7]不能和a[3] a[4] a[8]存在连续关系
a[8]不能和a[4]] a[5] a[7] a[9]存在连续关系
a[9]不能和a[4] a[5] a[6] a[8]存在连续关系。
我们发现有很多情况是重复的,在写代码的时候手动去个重就可以了:
AC代码
#include <bits/stdc++.h>
using namespace std;
int a[] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0};
int ans;
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[2]) == 1 ||
abs(a[1] - a[4]) == 1 ||
abs(a[1] - a[5]) == 1 ||
abs(a[1] - a[6]) == 1 ||
abs(a[2] - a[5]) == 1 ||
abs(a[2] - a[6]) == 1 ||
abs(a[3] - a[4]) == 1 ||
abs(a[3] - a[7]) == 1 ||
abs(a[3] - a[8]) == 1 ||
abs(a[4] - a[5]) == 1 ||
abs(a[4] - a[7]) == 1 ||
abs(a[4] - a[8]) == 1 ||
abs(a[4] - a[9]) == 1 ||
abs(a[5] - a[6]) == 1 ||
abs(a[5] - a[8]) == 1 ||
abs(a[5] - a[9]) == 1 ||
abs(a[6] - a[9]) == 1 ||
abs(a[7] - a[8]) == 1 ||
abs(a[8] - a[9]) == 1
)
return false;
return true;
}
void f(int k) {
if (k == 10) {
if (check()) {
ans++;
return ;
}
}
for (int i = k; i < 10; i++) { //0~9
{
int t = a[k];
a[k] = a[i];
a[i] = t;
}
f(k + 1); //递归
{
int t = a[k]; //回溯
a[k] = a[i];
a[i] = t;
}
}
}
int main() {
f(0);
cout << ans << endl;
return 0;
}