zoukankan      html  css  js  c++  java
  • 回溯算法

    回溯算法

    搜索与回溯是计算机解题中常用的算法,很多问题无法根据某种确定的计算法则来求解,可以利用搜索与回溯的技术求解。回溯是搜索算法中的一种控制策略。它的基本思想是:为了求得问题的解,先选择某一种可能情况向前探索,在探索过程中,一旦发现原来的选择是错误的,就退回一步重新选择,继续向前探索,如此反复进行,直至得到解或证明无解。

    如迷宫问题:进入迷宫后,先随意选择一个前进方向,一步步向前试探前进,如果碰到死胡同,说明前进方向已无路可走,这时,首先看其它方向是否还有路可走,如果有路可走,则沿该方向再向前试探;如果已无路可走,则返回一步,再看其它方向是否还有路可走;如果有路可走,则沿该方向再向前试探。按此原则不断搜索回溯再搜索,直到找到新的出路或从原路返回入口处无解为止。

    递归回溯法算法框架[一]

    int Search(int k)

     {

     for (i=1;i<=算符种数;i++)

      if (满足条件)

         {

        保存结果

        if (到目的地) 输出解;

                  else Search(k+1);

        恢复:保存结果之前的状态{回溯一步}

         }

     }

    递归回溯法算法框架[二]

    int Search(int k)

     {

       if  (到目的地) 输出解;

       else

        for (i=1;i<=算符种数;i++)

         if  (满足条件)

           {

            保存结果;

                         Search(k+1);

            恢复:保存结果之前的状态{回溯一步}

           }

     }

    【例1】素数环:从1到20这20个数摆成一个环,要求相邻的两个数的和是一个素数。

    【算法分析】

    非常明显,这是一道回溯的题目。从1开始,每个空位有20种可能,只要填进去的数合法:与前面的数不相同;与左边相邻的数的和是一个素数。第20个数还要判断和第1个数的和是否素数。

    【算法流程】

    1、数据初始化;   2、递归填数:判断第i个数填入是否合法;

    A、如果合法:填数;判断是否到达目标(20个已填完):是,打印结果;不是,递归填下一个;

    B、如果不合法:选择下一种可能;

    【参考程序】

     1 #include<cstdio>
     2 #include<iostream>
     3 #include<cstdlib>
     4 #include<cmath>
     5 using namespace std;
     6 bool b[21]={0};
     7 int total=0,a[21]={0};
     8 int search(int);                           //回溯过程
     9 int print();                               //输出方案
    10 bool pd(int,int);                          //判断素数
    11 int main()
    12 {
    13     search(1);
    14     cout<<total<<endl;                    //输出总方案数
    15 }
    16 int search(int t)
    17 {
    18     int i;
    19     for (i=1;i<=20;i++)                     //有20个数可选
    20      if (pd(a[t-1],i)&&(!b[i]))            //判断与前一个数是否构成素数及该数是否可用
    21       {
    22          a[t]=i;
    23          b[i]=1;
    24          if (t==20) { if (pd(a[20],a[1])) print();}
    25              else search(t+1);
    26          b[i]=0//一会儿变1一会儿变0.。。那么他的存在到底是干嘛的叻
    27       }
    28 }
    29 int print()
    30 {
    31    total++;
    32    cout<<"<"<<total<<">";
    33    for (int j=1;j<=20;j++)
    34      cout<<a[j]<<" ";
    35    cout<<endl; 
    36   }
    37 bool pd(int x,int y)
    38 {
    39     int k=2,i=x+y;
    40     while (k<=sqrt(i)&&i%k!=0) k++;
    41     if (k>sqrt(i)) return 1;
    42        else return 0;
    43 }

    ***总结来说呢。。回溯好像就是一种递归,满足了我就继续走,不满足掉头重新走啦。据说(好像就是)他能和神马图的联系在一起,但是很sad我不会图论哇。。打算求助小哥哥。。毕竟我老人家连例一代码还有不懂的地方。。好sad我貌似汉诺塔还没弄明白。。。OMG我都做了些神马。。。sadsad。。。。

     

     

  • 相关阅读:
    【2017中国大学生程序设计竞赛
    【hdu 4333】Revolving Digits
    【hihocoder 1554】最短的 Nore0061
    【2017中国大学生程序设计竞赛
    【Codeforces Beta Round #88 C】Cycle
    【2017 Multi-University Training Contest
    【Codeforces Round #429 (Div. 2) C】Leha and Function
    【Codeforces Round #429 (Div. 2) B】 Godsend
    【Codeforces Round #429 (Div. 2) A】Generous Kefa
    Single-stack real-time operating system for embedded systems
  • 原文地址:https://www.cnblogs.com/rax-/p/8620574.html
Copyright © 2011-2022 走看看