搭積木+寒假作業+方格填數 DFS解法
藍橋杯比賽關於 DFS 演算法總結方法以及套路分析
首先我們來看幾道java A組的題目,都是同一年的哦!!!
搭積木小明最近喜歡搭數字積木,
一共有10塊積木,每個積木上有一個數字,0~9。搭積木規則:
每個積木放到其它兩個積木的上面,並且一定比下面的兩個積木數字小。
最後搭成4層的金字塔形,必須用完所有的積木。下面是兩種合格的搭法:
0
1 2
3 4 5
6 7 8 90
3 1
7 5 2
9 8 6 4請你計算這樣的搭法一共有多少種?
請填表示總數目的數字。
注意:你提交的應該是一個整數,不要填寫任何多餘的內容或說明性文字。
public class test4 { int a[]=new int[20]; //java 陣列初始化值為0 int visit[]=new int[20]; //判斷是否使用過 static int count1=0; public void dfs1(int x){ if(x==10){ if(a[0]<a[1]&&a[0]<a[2] //這裡沒有進行剪枝操作,因為不方便 &&a[1]<a[3]&&a[1]<a[4]&&a[2]<a[4]&&a[2]<a[5] &&a[3]<a[6]&&a[3]<a[7]&&a[4]<a[7]&&a[4]<a[8]&&a[5]<a[8]&&a[5]<a[9]){ count1++; return; } } for(int i=0;i<10;i++){ if(visit[i]==0){ //深度搜索套路程式碼,只可意會 a[x]=i; visit[i]=1; dfs1(x+1); visit[i]=0; } } return; //這個return是當前面的所有的都不成立時回溯(return)到最初呼叫for迴圈內的dfs處 } public static void main(String[] args){ new test4().dfs1(0); System.out.println(count1); } }
結果:768
寒假作業
現在小學的數學題目也不是那麼好玩的。
看看這個寒假作業:□ + □ = □
□ - □ = □
□ × □ = □
□ ÷ □ = □
(如果顯示不出來,可以參見【圖1.jpg】)
每個方塊代表1~13中的某一個數字,但不能重複。
比如:
6 + 7 = 13
9 - 8 = 1
3 * 4 = 12
10 / 2 = 5以及:
7 + 6 = 13
9 - 8 = 1
3 * 4 = 12
10 / 2 = 5就算兩種解法。(加法,乘法交換律後算不同的方案)
你一共找到了多少種方案?
請填寫表示方案數目的整數。
注意:你提交的應該是一個整數,不要填寫任何多餘的內容或說明性文字。
public class test3 {
int a[]=new int[20]; //java 陣列初始化值為0
int visit[]=new int[20];
static int count=0;
public void dfs(int x){ //相當於剪枝操作
/*if(x>3&&a[1]+a[2]!=a[3]) //如果前三個數已經被取出來但不符合題設條件,則返回重找
return;
if(x>6&&a[4]-a[5]!=a[6]) //若前三個數滿足第一條,看4-6個數是否滿足第二個條件
return;
if(x>9&&a[7]*a[8]!=a[9]) //同上
return;
if(x>12&&a[12]*a[11]==a[10]) //如果所有條件均滿足,則讓count++
{
count++;
return;
}*/
if(x>12){
if((a[1]+a[2]==a[3])&&(a[4]-a[5]==a[6])&&(a[7]*a[8]==a[9])&&(a[12]*a[11]==a[10])){
count++;
return;
}
}
for(int i=1;i<14;i++){
if(visit[i]==0){ //深度搜索套路程式碼
a[x]=i;
visit[i]=1;
dfs(x+1);
visit[i]=0;
}
}
return; //這個return是當前面的所有的都不成立時回溯(return)到最初呼叫for迴圈內的dfs處
}
public static void main(String[] args){
new test3().dfs(1);
System.out.println(count);
}
}
結果: 64
第三題:
方格填數如下的10個格子
+--+--+--+
|0 | 1| 2|
+--+--+--+--+
| 3| 4| 5| 6|
+--+--+--+--+
| 7| 8| 9|
+--+--+--+(如果顯示有問題,也可以參看【圖1.jpg】)
填入0~9的數字。要求:連續的兩個數字不能相鄰。
(左右、上下、對角都算相鄰)一共有多少種可能的填數方案?
請填寫表示方案數目的整數。
注意:你提交的應該是一個整數,不要填寫任何多餘的內容或說明性文字。
public class test5 {
int a[]=new int[20]; //java 陣列初始化值為0
int visit[]=new int[20]; //判斷是否使用過
static int count1=0;
public void dfs1(int x){
if(x==10){
if(
(Math.abs(a[0]-a[1])!=1)&&
(Math.abs(a[0]-a[3])!=1)&&
(Math.abs(a[0]-a[4])!=1)&&
(Math.abs(a[0]-a[5])!=1)&&
(Math.abs(a[1]-a[2])!=1)&&
(Math.abs(a[1]-a[4])!=1)&&
(Math.abs(a[1]-a[5])!=1)&&
(Math.abs(a[1]-a[6])!=1)&&
(Math.abs(a[2]-a[5])!=1)&&
(Math.abs(a[2]-a[6])!=1)&&
(Math.abs(a[3]-a[0])!=1)&&
(Math.abs(a[3]-a[4])!=1)&&
(Math.abs(a[3]-a[7])!=1)&&
(Math.abs(a[3]-a[8])!=1)&&
(Math.abs(a[4]-a[5])!=1)&&
(Math.abs(a[4]-a[7])!=1)&&
(Math.abs(a[4]-a[8])!=1)&&
(Math.abs(a[4]-a[9])!=1)&&
(Math.abs(a[5]-a[6])!=1)&&
(Math.abs(a[5]-a[8])!=1)&&
(Math.abs(a[5]-a[9])!=1)&&
(Math.abs(a[6]-a[9])!=1)&&
(Math.abs(a[7]-a[8])!=1)&&
(Math.abs(a[8]-a[9])!=1)
){
count1++;
return;
}
/* if(a[0]!=a[1]&&a[0]!=a[3]&&a[0]!=a[4]&&a[0]!=a[5]
&&a[1]!=a[0]&&a[1]!=a[2]&&a[1]!=a[4]&&a[1]!=a[5]&&a[1]!=a[6]
&&a[2]!=a[1]&&a[2]!=a[5]&&a[2]!=a[6]
&&a[3]!=a[0]&&a[3]!=a[0]&&a[3]!=a[7]
&&a[4]!=a[0]&&a[4]!=a[1]&&a[4]!=a[3]&&a[4]!=a[5]&&a[4]!=a[7]&&a[4]!=a[8]&&a[4]!=a[9]
&&a[5]!=a[0]&&a[5]!=a[1]&&a[5]!=a[2]&&a[5]!=a[4]&&a[5]!=a[6]&&a[5]!=a[8]&&a[5]!=a[9]
&&a[6]!=a[1]&&a[6]!=a[2]&&a[6]!=a[5]&&a[6]!=a[9]
&&a[7]!=a[3]&&a[7]!=a[4]&&a[7]!=a[8]
&&a[8]!=a[3]&&a[8]!=a[4]&&a[8]!=a[5]&&a[8]!=a[7]&&a[8]!=a[9]
&&a[9]!=a[4]&&a[9]!=a[5]&&a[9]!=a[6]&&a[9]!=a[8]){
count1++;
return;
}*/
}
for(int i=0;i<10;i++){
if(visit[i]==0){ //深度搜索套路程式碼,只可意會
a[x]=i;
visit[i]=1;
dfs1(x+1);
visit[i]=0;
}
}
return; //這個return是當前面的所有的都不成立時回溯(return)到最初呼叫for迴圈內的dfs處
}
public static void main(String[] args){
new test5().dfs1(0);
System.out.println(count1);
}
}
執行結果: 1580