存粹做题感悟
方格填数
如下的10个格子
±-±-±-+
| | | |
±-±-±-±-+
| | | | |
±-±-±-±-+
| | | |
±-±-±-+
(如果显示有问题,也可以参看【图1.jpg】)
填入0~9的数字。要求:连续的两个数字不能相邻。
(左右、上下、对角都算相邻)
一共有多少种可能的填数方案?
请填写表示方案数目的整数。
注意:你提交的应该是一个整数,不要填写任何多余的内容或说明性文字。
答案:1580
分析
可以暴力,也可以全排列或者dfs,麻烦在于符合条件的判定比较冗长且杂。
暴力的话套一打for循环可以在中间点塞if判断减少循环次数,反而全排列或dfs只是末端判定,中间不好加判断语句,但用全排列或者dfs模板还是很简单的
1先开个一维数组存0到9,具体每个数组元素的位置如图(看了其他博主的博客也有用二维的也可以,但要注意边界和敲的时候多敲几个小括号而已)
2扔进全排列模板:由第0位一次添加直到凑齐
3扔进judge函数判断,具体位置如图
package 真题2016;
public class fanggetianshu6 {
static int counts=0;//计数君
public static void judge(int[]a) {//判定语句
if(Math.abs(a[0]-a[3])==1||Math.abs(a[0]-a[4])==1||Math.abs(a[0]-a[5])==1||Math.abs(a[0]-a[1])==1) {
return;
}else if(Math.abs(a[1]-a[4])==1||Math.abs(a[1]-a[5])==1||Math.abs(a[1]-a[6])==1||Math.abs(a[1]-a[2])==1) {
return;
}else if(Math.abs(a[2]-a[5])==1||Math.abs(a[2]-a[6])==1) {
return;
}else if(Math.abs(a[3]-a[7])==1||Math.abs(a[3]-a[8])==1||Math.abs(a[3]-a[4])==1) {
return;
}else if(Math.abs(a[4]-a[7])==1||Math.abs(a[4]-a[8])==1||Math.abs(a[4]-a[9])==1||Math.abs(a[4]-a[5])==1) {
return;
}else if(Math.abs(a[5]-a[8])==1||Math.abs(a[5]-a[9])==1||Math.abs(a[5]-a[6])==1) {
return;
}else if(Math.abs(a[6]-a[9])==1||Math.abs(a[7]-a[8])==1||Math.abs(a[8]-a[9])==1) {
return;
}else counts++;
}
public static void swap(int[]a,int i,int j) {//交换方法
int temp=a[i];
a[i]=a[j];
a[j]=temp;
}
public static void qpl(int[] a,int start) {
if(start==a.length) {//末端判定(即凑齐)
judge(a);
}else {
for(int i=start;i<a.length;i++) {
swap(a,i,start);//回溯
qpl(a,start+1);
swap(a,i,start);//回溯
}
}
}
public static void main(String[] args) {
// dfs或者全排列,一般都是末端验证,还没凑满10个数就加判断条件减少搜索次数也可以,但判断位置和判断条件不好确定
int[]a={0,1,2,3,4,5,6,7,8,9};//就0-9,直接创建方便点
qpl(a,0);
System.out.println(counts);
}
}