什麼時候遞歸?

當前層的須要使用下一層調用的結果,並且,各個層的調用之間知足必定的規律。
怎麼更好地終極理解遞歸算法html

遞歸算法的實現得以依賴於這種數據結構,棧的存在使得各層調用中的現場保護與恢復不須要人爲干預。node

遞歸算法的關鍵:【如何去理解遞歸,想到遞歸,運用遞歸ios

  1. 肯定基線條件(使程序終止的條件)
  2. 肯定遞歸條件(各層調用之間的規律)

例一:求1到100的和。算法

#include <stdio.h>

int sum(int x)
{
  if(x == 1) //基線條件
  {
    return 1;    
  }
  return sum(x-1) + x; //遞歸條件
}

int main()
{
  int ret = 0;
  ret = sum(100);
  printf("%d", ret);
  return 0;
}

用一個公式表達以下:網絡

\[ sum(100) = 100 + sum(99) = 100 + 99 + sum(98) = ... = 100 + 99 + ... + 2 + sum(1) \]數據結構

計算機求解時,將\(sum(x)\)\(x\)從100到2)依次壓入到棧中,直到\(x=1\)時,程序能夠計算出\(sum(1) = 1\),彈出\(sum(1)\),而後將\(sum(1)\)的計算結果返回用於計算\(sum(2)\),當計算出\(sum(2)\)後,返回結果,彈出\(sum(2)\),...,最終,直到計算出\(sum(100)\),彈出\(sum(100)\),棧空結束。函數

例二:藍橋杯: 六角填數spa

對於該問題,咱們使用遞歸算法是在不斷地向空白位置填充數字,明確目的後,咱們也肯定了遞歸條件。.net

  1. 基線條件:12個空填滿
  2. 遞歸條件:空白位置未填滿,進行下一步填充
#include <iostream>
using namespace std;

int pos[13] = {0};
int vis[13] = {0};
int line[6] = {0};

void dfs(int node)
{
  if(node == 1 || node == 2 || node == 12) //若是當前節點是三個網絡初始化時的任意一個節點
  {
    dfs(node+1); //遞歸條件:跳過當前節點,訪問下一個節點
    return;
  }
  else //若是當前節點沒有被訪問,則對當前節點進行賦值
  {
    if(node <= 12)
    {
      for(int num = 1; num < 13; num++) //遍歷12個數字
      {
        if(vis[num] == 0) //若是該數字沒有被使用過
        {
          vis[num] = 1; //如今使用這個數字
          pos[node] = num; //把如今這個數字賦值給當前訪問的結點
          dfs(node+1); //遞歸條件:給下一個點賦值(若是正常狀況知足,不會進入到下一行)
          //【重點理解】若是對全部節點都賦值後仍不知足題意,清除當前數字的標誌,
          // 令其在下一次仍然能夠使用該數字。
          vis[num] = 0; 
        }
      }       
    }
    else //已經對12個節點都進行了賦值,判斷當前網絡是否知足題意
    {
        line[0] = pos[1] + pos[3] + pos[6] + pos[8];
        line[1] = pos[1] + pos[4] + pos[7] + pos[11];
        line[2] = pos[8] + pos[9] + pos[10] + pos[11];
        line[3] = pos[2] + pos[3] + pos[4] + pos[5];
        line[4] = pos[2] + pos[6] + pos[9] + pos[12];
        line[5] = pos[5] + pos[7] + pos[10] + pos[12];
        if(line[0] == line[1] && line[1] == line[2] && line[2] == line[3] 
                              && line[3] == line[4] && line[4] == line[5])
        {// 基線條件:若是知足題意,打印結果
          cout << "pos[6] = " << pos[6] << endl;
          return; 
        }
        else
        {// 基線條件:若是不知足題意,結束本次函數
          return;
        }
    }
   
  }
}

int main()
{
  //初始化網絡參數
  pos[1] = 1;
  vis[1] = 1;
  pos[2] = 8;
  vis[8] = 1;
  pos[12]= 3;
  vis[3] = 1;
  dfs(1); //深度優先搜索算法
  return 0;
}

對於該問題的理解,能夠參考【轉載】深度優先搜索算法3d

相關文章
相關標籤/搜索