A,2,3,4,5,6,7,8,9 共9张纸牌排成一个正三角形(A按1计算)。要求每个边的和相等。 下图就是一种排法(如有对齐问题,参看p1.png)。 A 9 6 4 8 3 7 5 2 这样的排法可能会有很多。 如果考虑旋转、镜像后相同的算同一种,一共有多少种不同的排法呢? 请你计算并提交该数字。 注意:需要提交的是一个整数,不要提交任何多余内容。
代码如下:
public class Main{ static int count=0; static boolean bool[]=new boolean[10]; static int num[]=new int[10]; public static void main(String[] args) { dfs(1); System.out.println(count/3/2); } public static void dfs(int step) { if(step==10) { if(num[1]+num[2]+num[4]+num[6]==num[6]+num[7]+num[8]+num[9] &&num[1]+num[2]+num[4]+num[6]==num[1]+num[3]+num[5]+num[9]) { count++; } return; } for(int i=1;i<10;i++) { if(!bool[i]) { bool[i]=true; num[step]=i; dfs(step+1); bool[i]=false; } } } }
答案:144
回溯案例如下图所示:
解释:首先,让我们明确代码的功能:这是一个深度优先搜索(DFS)算法。条件是数组
num
中的前四个数字(1、2、4、6位)的和必须等于接下来的四个数字(6、7、8、9位)的和,同时也必须等于另一组四个数字(1、3、5、9位)的和。下面是每一步的详细解释:
初始化:
count
:初始化为0,用于记录满足条件的排列数量。bool[]
:一个长度为10的布尔数组,初始值全部为false,用于标记数字是否已经被使用。num[]
:一个长度为10的整数数组,用于存储当前排列的数字。主函数开始:
- 调用
dfs(1)
开始深度优先搜索。进入 dfs(1):
step
:当前为1,表示正在填充num
数组的第一个位置。开始循环(第一次循环,i=1):
bool[1]
:之前是false,现在设置为true,表示数字1已被使用。num[1]
:设置为1。- 递归调用
dfs(2)
。进入 dfs(2):
step
:现在为2,表示正在填充num
数组的第二个位置。- 循环中,
i
从1遍历到9,但1已经被使用(bool[1]
为true),所以跳过1。- 当
i
为2时,因为2还未被使用,所以bool[2]
设置为true,num[2]
设置为2,然后递归调用dfs(3)
。进入 dfs(3),以此类推,直到
dfs(10)
。到达 dfs(10):
- 此时,
num[]
数组已被完全填充。- 检查条件是否满足:
num[1]+num[2]+num[4]+num[6]
是否等于num[6]+num[7]+num[8]+num[9]
以及num[1]+num[2]+num[4]+num[6]
是否等于num[1]+num[3]+num[5]+num[9]
。- 如果条件满足,
count
增加1。回溯:
- 从
dfs(10)
返回,bool[9]
被设置为false,因为9在当前的排列中已被使用,但在其他可能的排列中可能还需要使用。- 类似地,
dfs(9)
返回,bool[8]
被设置为false,依此类推,直到最初的dfs(1)
返回。主函数结束:
- 打印
count
的值,即满足条件的排列数量。需要注意的是,在每次递归调用
dfs(step+1)
后,都会通过bool[i]=false
进行回溯,这是深度优先搜索中常见的做法,用于撤销当前的选择,以便尝试其他可能性。