0x01.问题
在2行5列的格子中填入1到10的数字。
要求:相邻的格子中的数,右边的大于左边的,下边的大于上边的。
如下图所示的2种,就是合格的填法。
请你计算一共有多少种可能的方案。
注:本题来自蓝桥杯2015年决赛,方格填数,为填空题。
0x02.分析问题
从题目,我们可以得到,这些填入的数字应该满足以下条件:
- 右边的数比左边大。
- 下面的数比上面的数大。
- 第一个格子一定是1,最后一个各自一定是10,其余每个各自都必须在一定的范围内。
- 数字不能重复。
很明显,暴力枚举法就诞生了,只需8个循环,对每种组合进行一一判断即可。
10个数字依次填入,不满足就退回去找其他的数字,这是一个回溯的过程,所以我们可以使用深度优先搜索来解决此问题。
0x03.解决代码--暴力枚举
#include<stdio.h>
int a[2][5];
int cou = 0;
int check()
{
for (int i = 1; i < 5; i++)
{
if (a[0][i] < a[0][i-1])
{
return 0;
}
if (a[1][i] < a[1][i-1])
{
return 0;
}
if (a[1][i] < a[0][i])
{
return 0;
}
}
return 1;
}
int main()
{
for (int i = 0; i < 2; i++)
{
for (int j = 0; j < 5; j++)
{
a[i][j] = 0;
}
}
int b[8];
a[0][0] = 1;
a[1][4] = 10;
for (b[0] = 2; b[0] <= 6; b[0]++)
{
a[0][1] = b[0];
for (b[1] = 3; b[1] <= 7; b[1]++)
{
if (b[1] == b[0])
continue;
a[0][2] = b[1];
for (b[2] = 4; b[2] <= 8; b[2]++)
{
if (b[2] == b[1] || b[2] == b[0])
continue;
a[0][3] = b[2];
for (b[3] = 5; b[3] <= 9; b[3]++)
{
if (b[3] == b[2] || b[3] == b[1] || b[3] == b[0])
continue;
a[0][4] = b[3];
for (b[4] = 2; b[4] <= 6; b[4]++)
{
if (b[4] == b[3] || b[4] == b[2] || b[4] == b[1] || b[4] == b[0])
continue;
a[1][0] = b[4];
for (b[5] = 4; b[5] <= 7; b[5]++)
{
if (b[5] == b[4] || b[5] == b[3] || b[5] == b[2] || b[5] == b[1] || b[5] == b[0])
continue;
a[1][1] = b[5];
for (b[6] = 6; b[6] <= 8; b[6]++)
{
if (b[6] == b[5] || b[6] == b[4] || b[6] == b[3] || b[6] == b[2] || b[6] == b[1] || b[6] == b[0])
continue;
a[1][2] = b[6];
for (b[7] = 8; b[7] <= 9; b[7]++)
{
if (b[7] == b[6] || b[7] == b[3] || b[7] == b[2])
continue;
a[1][3] = b[7];
if (check())
{
cou++;
}
}
}
}
}
}
}
}
}
printf("%d\n", cou);
}
0x04.解决代码--DFS
#include<stdio.h>
int a[2][5];
int cou = 0;
int flag[10];
int check()
{
if (a[1][0] < a[0][0])
return 0;
for (int i = 1; i < 5; i++)
{
if (a[0][i] < a[0][i-1])
{
return 0;
}
if (a[1][i] < a[1][i-1])
{
return 0;
}
if (a[1][i] < a[0][i])
{
return 0;
}
}
return 1;
}
void DFS(int num)
{
if (num == 10)
{
if (check())
{
cou++;
}
return;
}
for (int i = 1; i <= 10; i++)
{
if (flag[i] == 0)
{
flag[i] = 1;
a[num / 5][num % 5] = i;
DFS(num + 1);
flag[i] = 0;
}
}
}
int main()
{
for (int i = 0; i < 2; i++)
{
for (int j = 0; j < 5; j++)
{
a[i][j] = 0;
}
}
for (int i = 0; i < 10; i++)
{
flag[i] = 0;
}
DFS(0);
printf("%d\n", cou);
}
答案:42