题目来源:第七届蓝桥杯省赛C++B组
算法标签:全排列
题目描述:
如下的10个格子
+--+--+--+ | | | | +--+--+--+--+ | | | | | +--+--+--+--+ | | | | +--+--+--+
(如果显示有问题,也可以参看【图1.jpg】)
填入0~9的数字。要求:连续的两个数字不能相邻。
(左右、上下、对角都算相邻)
一共有多少种可能的填数方案?
请填写表示方案数目的整数。
注意:你提交的应该是一个整数,不要填写任何多余的内容或说明性文字。
题目答案:
1580
题目思路:
题目是格子填入数,连续两个数字不能相邻。
那么换句话说,我们得到判断条件,一个格子与上下左右对角绝对差值==1则不符合条件
。
很明显这道题是全排列判断,每个格子尝试不同的数字,那么我们现在的问题转换为了一个格子怎么做判断。
我们先假设第一个位子
将周边的距离为1的位子全部标记。
则第二个位子的标记方式即为下图,不用判断与上一个的关系,因为位于上一个时,已经判断过了。
当我们往下移动一层时,则如下图,上一层的两个与当前位子相邻的位子
与前一个位子
都在之前的过程中与当前的位子判断过了。
让我们下沉到最后一层,即为下图,上一层,当前层左边都判断过,下一层没有:
则我们很容易得出代码!
题目代码:
#include <iostream>
#include <algorithm>
#include <cmath>
using namespace std;
int a[10];
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)return false;
if (abs(a[1] - a[2]) == 1 || abs(a[1] - a[4]) == 1 || abs(a[1] - a[5]) == 1 || abs(a[1] - a[6]) == 1)return false;
if (abs(a[2] - a[5]) == 1 || abs(a[2] - a[6]) == 1)return false;
if (abs(a[3] - a[4]) == 1 || abs(a[3] - a[7]) == 1 || abs(a[3] - a[8]) == 1)return false;
if (abs(a[4] - a[5]) == 1 || abs(a[4] - a[7]) == 1 || abs(a[4] - a[8]) == 1 || abs(a[4] - a[9]) == 1)return false;
if (abs(a[5] - a[6]) == 1 || abs(a[5] - a[8]) == 1 || abs(a[5] - a[9]) == 1)return false;
if (abs(a[6] - a[9]) == 1)return false;
if (abs(a[7] - a[8]) == 1 || abs(a[8] - a[9]) == 1)return false;
return true;
}
int main()
{
for (int i = 0; i <= 9; i++)a[i] = i;//初始化
do
{
if (check())ans++;//如果符合条件则答案加1
} while (next_permutation(a, a + 10));
cout << ans;
return 0;
}