1. 程式人生 > 其它 >靜態路由綜合實驗

靜態路由綜合實驗

今天寫了這道題才明白遞迴搜尋樹的含義

從 1∼n 這 n 個整數中隨機選出 m 個,輸出所有可能的選擇方案。

輸入格式
兩個整數 n,m ,在同一行用空格隔開。

輸出格式
按照從小到大的順序輸出所有方案,每行 1 個。

首先,同一行內的數升序排列,相鄰兩個數用一個空格隔開。

其次,對於兩個不同的行,對應下標的數一一比較,字典序較小的排在前面(例如 1 3 5 7 排在 1 3 6 8 前面)。

資料範圍
n>0 ,
0≤m≤n ,
n+(n−m)≤25
輸入樣例:
5 3
輸出樣例:
1 2 3 
1 2 4 
1 2 5 
1 3 4 
1 3 5 
1 4 5 
2 3 4 
2 3 5 
2 4 5 
3 4 5 
思考題:如果要求使用非遞迴方法,該怎麼做呢?

首先看這道題,一樣熟悉的題目,只不過變成挑選m個數字出來。

最初的版本

import java.util.*;

public class Main{
    static int N = 30;
    static int n;
    static int m;
    static int[] st = new int[N];
    static boolean[] vis = new boolean[N];
    public static void main(String[] args){
        Scanner sc = new Scanner(System.in);
        n = sc.nextInt();
        m = sc.nextInt();
        dfs(0);
    }

    public static void dfs(int u){
        //u表示你在第幾層,同時也表示你在填第幾個空
        //比如第0層,預設為0
        //在第一層時,你挑選哪個來填第一個空
        if(u == m){
            for(int i = 0; i < m; i++){
                System.out.printf("%d ",st[i]);
            }
            System.out.println();
            return;
        }
        //i從1開始,所以每次遞迴進去的時候都會從首位開始找,如果被使用過了,就跳到下一個數
        //所以就沒有思考有沒有升序的思考
        for(int i = 1; i <= n; i++){
            if(!vis[i]){
                st[u] = i;
                vis[i] = true;
                dfs(u + 1);
                vis[i] = false;   
            }
        }
    }
}

一開始沒有考慮到升序的問題,所以就造成跟之前排列相似,u表示的層數,

然後我就想,如果要考慮升序的話,也就是說你每次遞迴進來的時候,都要根據上一個選的數字來挑選下一個數

比如你在2層的時候,在挑選第三個數時,我們用1 3 _舉例,當我們選完3時,我們為了升序肯定是不能選2的,所以這裡我有兩種思路

一種是你可以繼續遍歷2,但是得加個條件,就是上一個數要大於當前數才行,但這樣會浪費一次判斷

另一種是類似剪枝的思想,就是你儲存上一個的狀態值 + 1,在下一個遞迴時,就從那個位置開始遍歷,這樣就可以了

import java.util.*;
/**
 *寫了這道題才開始理解的遞迴的含義
 * 首先是
 * 
 * 
 * 
 * 
 */
public class Main{
    static int N = 30;
    static int n;
    static int m;
    static int[] st = new int[N];
    static boolean[] vis = new boolean[N];
    public static void main(String[] args){
        Scanner sc = new Scanner(System.in);
        n = sc.nextInt();
        m = sc.nextInt();
        dfs(0,1);
    }
    
    public static void dfs(int u,int start){
        if(u == m){
            for(int i = 0; i < m; i++){
                System.out.printf("%d ",st[i]);
            }
            System.out.println();
            return ;
        }
        
        for(int i = start; i <= n; i++){
            if(!vis[i]){
                st[u] = i;
                vis[i] = true;
                //儲存此時選的數字
                dfs(u + 1,i + 1);
                vis[i] = false;
                
            }
        }
    }
}