程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> C語言 >> C++ >> 關於C++ >> 算法詳解之回溯法詳細完成

算法詳解之回溯法詳細完成

編輯:關於C++

算法詳解之回溯法詳細完成。本站提示廣大學習愛好者:(算法詳解之回溯法詳細完成)文章只能為提供參考,不一定能成為您想要的結果。以下是算法詳解之回溯法詳細完成正文


實際幫助:

回溯算法也叫摸索法,它是一種體系地搜刮成績的解的辦法。回溯算法的根本思惟是:從一條路往前走,能進則進,不克不及進則退回來,換一條路再試。用回溯算法處理成績的普通步調為:

1、界說一個解空間,它包括成績的解。

2、應用適於搜刮的辦法組織解空間。

3、應用深度優先法搜刮解空間。

4、應用限界函數防止挪動到弗成能發生解的子空間。

成績的解空間平日是在搜刮成績的解的進程中靜態發生的,這是回溯算法的一個主要特征。

照樣誰人基調,不愛好純實際的器械,愛好應用例子來說訴實際,在算法系列總結:靜態計劃(解公司外包本錢成績) 的那一節外面 我們舉得是經典的0-1背包成績,在回溯算法外面也有一些很經典的成績,固然,靜態計劃的0-1背包成績其實也能夠應用回溯算法來解。在諸如斯相似的求最優解的成績中,年夜部門其實都可以用回溯法來處理,可以以為回溯算法一個”通用解題法“,這是由他摸索性的行動決議的,就比如求一個最優解,我能夠沒有很好的概念曉得怎樣做會更快的求出這個最優解,然則我可以測驗考試一切的辦法,先摸索性的測驗考試每個組合,看看究竟通欠亨,假如欠亨,則折歸去,由比來的一個節點持續向前測驗考試其他的組合,如斯重復。如許一切解都出來了,在做一下比擬,能求不出最優解嗎?

例子先行,如今我們來看看經典的N後成績

成績描寫:在n*n格的棋盤上放置彼此不受進擊的n個皇後。依照國際象棋的規則,皇後可以進擊與的地方在統一行或統一列或統一斜線上的棋子。n後成績等價於在n*n格的棋盤上方置n個皇後,任何2個皇後不放在統一行或統一列或統一斜線上。我們須要求的是可放置的總數。
 

根本思緒:   用n元組x[1;n]表現n後成績的解。個中,x[i]表現皇後i放置在棋盤的第i行的第x[i]列。因為不允許將2個皇後放在統一列上,所以解向量中的x[i]互不雷同。2個皇後不克不及放在統一斜線上是成績的模糊束。關於普通的n後成績,這一模糊束前提可以化成顯束縛的情勢。假如將n*n 格的棋盤看作二維方陣,其行號從上到下,列號從左到右順次編號為1,2,...n。從棋盤左上角到右下角的主對角線及其平行線(即斜率為-1的各斜線)上,2個下標值的差(行號-列號)值相等。同理,斜率為+1的每條斜線上,2個下標值的和(行號+列號)值相等。是以,若2個皇後放置的地位分離是(i,j)和(k,l),且 i-j = k -l 或 i+j = k+l,則解釋這2個皇後處於統一斜線上。以上2個方程分離等價於i-k = j-l 和 i-k =l-j。由此可知,只需|i-k|=|l-j|成立,就注解2個皇後位於統一條斜線上。

1、從空棋盤起,逐行放置棋子。
2、每在一個結構中放下一個棋子,即推演到一個新的結構。
3、假如以後行上沒有可正當放置棋子的地位,則回溯到上一行,從新布放上一行的棋子。
代碼:


#include <stdio.h> 
#include <math.h> 
#include<stdlib.h> 
static int n,x[1000]; 
static    long sum; 
int Place(int k) 

for(int j=1;j <k; j++) 
    if((abs(k-j) == abs(x[j]-x[k]))||(x[j]==x[k])) return 0; 
     return 1; 
  }


void Backtrak(int t) 

   if(t>n) sum++; 
   else 
       for(int i=1; i <= n; i++) 
       { 
            x[t] =i; 
            if(Place(t))Backtrak(t+1); 
       } 
}


int main() 

    int nn; 
    while(scanf("%d",&nn)!=EOF) 
    { 
    n=nn; 
    sum=0; 
    for(int i=0;i<=n;i++) 
    x[i]=0; 
    Backtrak(1); 
    printf("%d\n",sum); 

}

這段代碼有需要說明一下,Place(int)即測驗考試看能否可以,假如弗成以則回退到t+1層,再測驗考試其他的組合。

這裡也道出了回溯算法的焦點思惟:但當摸索到某一步時,發明本來選擇其實不優或達不到目的,就退回一步從新選擇

算法理論:

成績描寫:在一個n*n的網格裡,每一個網格能夠為“牆壁”(用‘X'表現)和“街道”(用‘.'表現)。如今在街道放置堡壘,每一個堡壘可以向高低閣下四個偏向開仗,槍彈射程無窮遠。牆壁可以阻攔槍彈。問最多能放置若干個堡壘,使它們彼此不會相互摧毀。

以下面四張圖,牆壁用黑正方形表現,街道用空白正方形表現,圓球就代表堡壘。1,2,3是准確的,4,5是毛病的。認為4,5外面在某一行或許某一列有兩個堡壘,如許他們就會相互進擊了。意思明確了嗎?能夠我的表達很不清楚,呵呵….

輸出輸入示例


Sample input:
      ——————輸出的n值 
.X.. 
.... 

XX..
.... 

XX 
.X 
.X. 
X.X 
.X. 
.... 
.... 
.... 
....

Sample output:


初拿到這個成績,你會不會想到回溯算法呢?有人說遍歷牆的地位,然後再牆的高低閣下四個格子放置堡壘會獲得最優解,這個我沒有驗證過,細細的用筆劃了畫,似乎是這麼回事,然則許多時刻要曉得最優解用甚麼辦法是很難發明的,應用通用解題辦法回溯法,我們可以在一片茫然的時刻開端我們的編程

起首我們來剖析一下這個成績:應用回溯法,我們測驗考試每種能夠放置的情形,然落後行斷定能否知足請求,若不知足,測驗考試放到下一個單位格,如斯重復,終究,我們將一切能夠放置的情形全體遍歷出來了,連一切情形都出來了,難不成還找不到最優解嗎?哈哈。。說做就做…


#include <stdio.h>
     char map[4][4];
     int best,n;
     int canput(int row, int col)
     {
        int i;
        for (i = row - 1; i >= 0; i--)
        {
          if (map[i][col] == 'o') return 0;
          if (map[i][col] == 'x') break;
        }
        for (i = col - 1; i >= 0; i--)
        {
          if (map[row][i] == 'o') return 0;
          if (map[row][i] == 'x') break;
        }
        return 1;
     }

     void solve(int k,int tot)
     {
        int x,y;
        if(k==n*n)
        {
          if(tot>best)
          {
           best=tot;   return;
          }
        }
        else
        {
          x=k/n;
          y=k%n;
          if((map[x][y]=='.') && (canput(x,y) ) )
          {
            map[x][y]='o';
            solve(k+1,tot+1);
            map[x][y]='.';
          }
         solve(k+1,tot);
         }
      }

     int main()
     {
        int i,j;
        scanf("%d",&n);
        while(n>0)
        {
          for(i=0;i< n;i++)
             for(j=0;j< n;j++)
                 scanf("%1s",&map[i][j]);
          best=0;
          solve(0,0);
          printf("%d\n",best);
          n=0;                            
          scanf("%d",&n);
        }
        return 0;
 }

對下面的代碼做一下點說明,canput是做磨練的,磨練放在某個所在究竟行不可得通,solve才是真正停止遞歸回溯的函數。。

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved