1. 程式人生 > >搭積木+寒假作業+方格填數 DFS解法

搭積木+寒假作業+方格填數 DFS解法

藍橋杯比賽關於 DFS 演算法總結方法以及套路分析

首先我們來看幾道java A組的題目,都是同一年的哦!!!


搭積木

小明最近喜歡搭數字積木,
一共有10塊積木,每個積木上有一個數字,0~9。

搭積木規則:
每個積木放到其它兩個積木的上面,並且一定比下面的兩個積木數字小。
最後搭成4層的金字塔形,必須用完所有的積木。

下面是兩種合格的搭法:

   0
  1 2
 3 4 5
6 7 8 9

   0
  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