回溯算法

回溯算法本质是穷举,实现手段是递归,在递归的每个阶段,做如下操作:

1.预占资源

2.递归处理子问题

3.若失败,回溯,释放资源

收费公路重建问题:给定N个点p_{1},p_{2},...,p_{N},都位于x轴上,x_{i}p_{i}点的坐标,那么对于这N个点,有O(N^2)个两点之间的距离,可以花费O(N^{2}logN)时间排序,得到一个距离的集合。收费公路重建问题是,从这些距离重新构建一个点集。代码如下:

/* 收费公路重建问题 */
int Turnpike(int X[], DistSet D, int N)
{
    /* 第一个节点放在坐标0,最后一个节点显然能获取到,取剩余节点中距离最大的,放在右边,
     * 这些要求不失一般性*/
    X[1] = 0;
    X[N] = DeleteMax(D);
    X[N - 1] = DeleteMax(D);
    if (X[N] - X[N - 1] is in D)
    {
        Remove(X[N] - X[N - 1], D);
        return Place(X, D, N, 2, N - 2);
    }
    return false;
}

/* 收费公路重建问题核心例程 */
int Place(int X[], DistSet D, int N, int Left, int Right)
{
    int DMax, Found = false;

    /* 递归终止条件,集合中没有距离了,也就是所有节点都被处理好了 */
    if (D is empty)
        return True;
    /* 找集合中的最大距离 */
    DMax = FindMax(D);

    /* 将点放在右边,对left和right中间的所有点,都在集合D中有距离 */
    if (X[j] - DMax is in D for all 1 <= j <left, Right < j <= N)
    {
        /* 放置点,移除所有距离,递归剩下的部分 */
        X[Right] = DMax;
        for (1 <= j < left, Right < j <= N)
            Delete(X[j] - DMax, D);
        Found = Place(X, D, N, Left, Right - 1);

        /* 若失败了,那么回溯,回滚资源 */
        if (!Found)
            for (1 <= j < left, Right < j <= N)
                Insert(X[j] - DMax, D);
    }
    
    /* 放在右边失败了,尝试放在左边 */
    if (!Found && X[N] - DMax - X[j] is in D for all 1 <= j < left,
            Right < j<= N)
    {
        X[Left] = X[N] - DMax;
        for (1 <= j < left, Right < j <= N)
            Delete(X[N] - DMax - X[j], D);
        Found = Place(X, D, N, Left + 1, Right);

        if (!Found)
            for (1 <= j < left, Right < j <= N)
                Insert(X[N] - DMax - X[j], D);
    }
    return Found;
}

时间分析:若不回溯,那么时间是O(N^2),排序需要时间O(N^{2}logN),总时间就是O(N^{2}logN),一般来说若点分布均匀,那么在整个过程中会发生一次回溯

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值