馬走日問題——回溯法(python&&JAVA)


了解了八皇后問題之后我們再來看一下大同小異的馬走日問題。

問題描述:在n*m的棋盤中,馬只能走"日"字。馬從位置(x,y)出發,把棋盤的每一格都走一次且只走一次。找出所有路徑。

 我們以5*4為例,還是將每個格子都標上數字。每個數字都是兩位,十位數字表示該格子所在的行,而個位數字表示該格子所在的列。

 這個問題同樣是兩個限制條件:1.每一個格子都走,且每個格子只走一次。2.必須走日字

那么什么情況算是走了日字呢?有什么規律嗎?

1.左下右上橫日字跳法(起始方格與終止方格數字之差為8)

             

 2.左上右下橫日字跳法(起始方格與終止方格數字之差為12)

               

 3.左下右上豎日字跳法(起始方格與終止方格數字之差為19)

         

4.左上右下豎日字跳法(起始方格與終止方格數字之差為21)

          

限制條件找到了,我們還是找“馬”的存儲結構,這里我們依然選擇一維數組:因為每個格子只能走一次,所以也符合一維數組的存儲特性,即一個索引對應一個元素。

python實現:

while True:
    arr1 = []
    n = int(input("棋盤行數:"))                       #輸入行數
    m = int(input("棋盤列數:"))                       #輸入列數
    xx = int(input("起始行標:"))                      #輸入起始行標號
    yy = int(input("起始列標:"))                      #輸入起始列標號
    for x in range(n):
        for y in range(m):
            a = 10*x+y                                #通過行列轉換成方格中的數字
            arr1.append(a)
    num = 0
    def  horse(arr,finish_line=1):
        arr[0] = xx*10+yy                              #通過起始位置的行列標號轉換成起始位置方格中的數字
        flag = True
        if finish_line == len(arr):
            global num
            num += 1
            print("第%s種走法:" %num)
            for i in arr:                               #將方格中的元素轉化為下標的形式輸出
                mm = str(int(i/10))
                nn = str(int(i%10))
                print("("+mm+","+nn+")")
            # print(arr)
            return 0
        for stand in arr1:                              #保證馬一直在棋盤范圍內活動
            arr[finish_line] = stand
            # print(arr)
            if finish_line >= 1:                         #從初始位置的下一個位置判斷是否與上一個位置成日字
                if abs(arr[finish_line] - arr[finish_line - 1]) != 8 and abs(arr[finish_line] - arr[finish_line - 1]) != 12 and abs(arr[finish_line] - arr[finish_line - 1]) != 19 and abs(arr[finish_line] - arr[finish_line - 1]) != 21:
                    flag = False
                else:
                    flag = True
            for line in range(finish_line):
                if arr[finish_line] == arr[line]:        #判斷當前位置之前是否被走過
                    flag = False
            if flag == True:
                horse(arr,finish_line+1)
    if __name__ == '__main__':
        horse([None]*n*m)
        print("
一共%s種走法" %num)

JAVA實現:

import java.util.Scanner;
import java.util.Arrays;
public class horse {
    public static int num=0;
//    public static int []arr1 = new int[20];
    public static void main(String[] args) {
        Scanner sc = new Scanner(System.in);           //初始化的輸入操作
        System.out.println("棋盤高:");
        int height = sc.nextInt();
        System.out.println("棋盤寬:");
        int width = sc.nextInt();
        System.out.println("起始橫坐標:");
        int startx = sc.nextInt();
        System.out.println("起始縱坐標:");
        int starty = sc.nextInt();
        int []arr = new int[height*width];
        int []arr1 = new int[height*width];            //arr1列表用來存放所有格子,同時保證了出界的問題 int i=0;
              for(int x=0; x<height; x++){
                 for(int y=0; y<width;y++){
                     arr1[i++]=10*x+y;
             }
          }
        System.out.println(Arrays.toString(arr1));
        arr[0] = 10*startx+starty;
        int finish_index = 1;
        int node_num = height*width;
        horse_ri(arr,arr1,finish_index);
        System.out.printf("共%d種走法",num);
    }
    static void horse_ri(int arr[],int arr1[],int finish_index){
         boolean flag=true;
         if(finish_index==arr.length){           
           num++;
           System.out.printf("第%d種走法",num);
           System.out.println(Arrays.toString(arr));
           return;
         }
         for(int ind=1;ind<arr1.length; ind++){
             arr[finish_index]=arr1[ind];
             flag = true;
//不是日字的情況
if((Math.abs(arr[finish_index]-arr[finish_index-1])!=8)&&(Math.abs(arr[finish_index]-arr[finish_index-1])!=12)&&(Math.abs(arr[finish_index]-arr[finish_index-1])!=19)&&(Math.abs(arr[finish_index]-arr[finish_index-1])!=21)){ flag = false; }
//之前走過的格子
for(int index=0;index<finish_index;index++){ if(arr[finish_index]==arr[index]){ flag = false; } } if(flag==true){ horse_ri(arr,arr1,finish_index+1); } } } }


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM