复习回溯算法

回溯算法也叫试探法,它是一种系统地搜索问题的解的方法。 回溯算法的基本思想是:从一条路往前走,能进则进,不能进则退回来,换一条路再试。 问题的解空间通常是在搜索问题的解的过程中动态产生的,这是回溯算法的一个重要特性。 N皇后问题是一个非常有名的问题,目前最快的解决思路用到回溯算法,大家都在算法优化上做文章,好象目前普通计算机可以在10秒内搞定N<20的N_queen问题了 关于N皇后的问题我想后面专门找个时间好好再研究一下,(最近有些忙,老大给我一个任务,去研究一下WinCE和Symbian平台的并发解决方案,与我们的平台做对比,如果能认识一个相关平台的专家就好了。) 言归正传,下面通过一个实例加深对回溯算法的认识。 例:设有一个 n × m 的棋盘 (2<=n<=50,2<=m<=50),在棋盘上任一点有一个中国象棋马, 马走的规则为: 1 、马走日字 2 、马只能向右走 输入n , m 后,同时输入马起始的位置和终点的位置,试找出从起点到终点的所有路径的数目(若不存在从起点到终点的路径 , 则输出 0 )。 例如: (n=10,m=10),(1,5)( 起点 ),(3,5)( 终点 ) , 输出: 2 (即由 (1,5) 到 (3,5) 共有 2 条路径 ) 两种方法: ________________________________________________________________________ 一是递归 略 ________________________________________________________________________ 二是回溯 回溯法都是类似思路,所以程序的流程也是类似的,大致流程参照如下,任何回溯法问题都可套用。
    // 记录当前地点

    ii current = ii(stratx, starty);

    // 记录回溯的地点

    ii backtarce(current);

    // 记录路径,堆栈的作用

    vii path;



    起点压栈 // 这个灵活使用



    while(true)

    {

        if (是终点)

        {

            // 取决于找一个路径即可还是找所有路径个数

            return or not

        }



        // 判断是否有路径可走,要考虑到回溯回来的位置

        //(这个判断条件是所有回溯法解决问题的关键)

        if (是否有路)

        {

            排除掉回溯的路径后, 选一条路径



            当前路径压栈

        }

        else

        {

            if (栈不为空)

            {

                退栈,回溯

            }

            else

            {

                全部找完,退出

            }

        }

    }

    
________________________________________________________________________ 完整代码
// china xiangqi horse

#include <iostream>

#include <vector>



using namespace std;



int N,M;



typedef pair<int, int> ii;

typedef vector< pair<int, int> > vii;



int main()

{

    // 地图边界

    cin >> N >> M;

    L.clear();

    int stratx,starty;

    int endx,endy;

    cin >> stratx >> starty;

    cin >> endx >> endy;



    // 记录当前地点

    ii current = ii(stratx, starty);

    // 记录回溯的地点

    ii backtarce(current);

    // 记录路径

    vii path;

    // 

    int sum = 0;



    // 起点压栈

    path.push_back(current);



    while(true)

    {

        // 是否终点,是的话打印路径

        if (current == ii(endx, endy))

        {

    #if 1

            for( vii::iterator it = path.begin() ; it != path.end(); it++)

            {

                if (it != path.begin()) cout << "->";

                cout << "(" << (*it).first << "," <<  (*it).second<< ")";

            }

            cout << endl;

    #endif

            ++sum;



            // return main(); // 如果只要找一条,则打开

        }



        int less = backtarce.second - current.second;



        // 是否有路径可走

        if ((current.first < endx) 

            && (current.second > 0) 

            && (current.second <= M)

            && (less != -2))

        {

            // 排除掉回溯的路径后, 选一条路径

            if (less == 2){

                current.first += 2;

                current.second += 1;

            }else if (less == 1){

                current.first += 2;

                current.second -= 1;

            }else if (less == -1){

                current.first += 1;

                current.second -= 2;

            }else{

                current.first += 1;

                current.second += 2;

            }



            // 当前路径压栈

            path.push_back(current);

            backtarce = current;

        }

        else

        {

            // 栈是否为空

            if (!path.empty())

            {

                // 退栈,回溯

                backtarce = path.back();

                path.pop_back();

                current = path.back();

            }

            else

            {

                // 全部找完,退出

                break;

            }

        }

    }



    cout << "sum:" << sum << endl;

#endif

    return main();

}
  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值