一、问题描述
今有7对数字:两个1,两个2,两个3,…两个7,把它们排成一行。
要求,两个1间有1个其它数字,两个2间有2个其它数字,以此类推,两个7之间有7个其它数字。如下就是一个符合要求的排列:
17126425374635
当然,如果把它倒过来,也是符合要求的。
请你找出另一种符合要求的排列法,并且这个排列法是以74开头的。
思路:(难度在于将排列问题转变为深搜填数问题)
第一思路就是深搜,找到这个排列,再依次判断是不是符合排列,但对于深搜14个数复杂度实在太高,所以我应该将深搜的思路转化为填数的思路,应该像横向走迷宫填数的思路去解决,
故我们应确定这里的深搜参数为所填的数,而不是位数
能对深搜剪枝就剪枝
7,4位已经确定,那7,4不须深搜,深搜填入两个数即可,且这两个数的距离为这个数的数值
初始化数组,0作为深搜的标记,表示未填数
static int[] arr= {0,7,4,0,0,0,0,4,0,7,0,0,0,0,0};
注意这里为了方便取数位我们设一个大小为15的数组
- 依次将1~6(除4)的数填入数组下标,最后结果不符,回溯清除填入的数据
if (num>=7) {//找到了14个数
for (int j = 1; j < arr.length; j++) {
System.out.print(arr[j]);
}
return;
}
if (num==4) {//4不用深搜,跳过
num++;
}
注意这里num==4时应当选择填5,num++;
for (int j = 3; j < 14; j++) {//从第3位开始填数,注意最后一位不可填
if (arr[j]==0&&j+num+1<=14&&arr[j + num + 1] == 0) {
arr[j]=num;
arr[j+num+1]=num;
dfs(num+1);
arr[j]=0;
arr[j+num+1]=0;//回溯清0;
}
}
代码
package competion2020;
import java.util.ArrayList;
public class 开头为74的排列法 {
static int[] arr= {0,7,4,0,0,0,0,4,0,7,0,0,0,0,0};
public static void main(String[] args) {
dfs(1);//从数字1开始填
}
private static void dfs(int num) {
// TODO 自动生成的方法存根
//深搜填数类
if (num>=7) {//找到了14个数
for (int j = 1; j < arr.length; j++) {
System.out.print(arr[j]);
}
return;
}
if (num==4) {//4不用深搜,跳过
num++;
}
for (int j = 3; j < 14; j++) {//从第3位开始填数,注意最后一位不可填
if (arr[j]==0&&j+num+1<=14&&arr[j + num + 1] == 0) {
arr[j]=num;
arr[j+num+1]=num;
dfs(num+1);
arr[j]=0;
arr[j+num+1]=0;//回溯清0;
}
}
}
}