剪枝法观点下的旅行商问题(TSP)

1. 构建基本的穷举搜索骨架

int n;
int dst[100][100];
int best;

const int INF = 987654321;

// 初始状态下,path 存入第一节点,visited 全部元素为 false,curLen = 0;
void search(vector<int>& path, vector<bool>& visited, int curLen){
    if (best <= curLen)
        return;
    int here = path.back();
    if (path.size() == n) {
        best = min(best, curLen+dst[here][0]);
        return;
    }
    for (int next = 0; next < n; ++next){
        if (visited[next])
            continue;
        visited[next] = true;
        path.push_back(next);
        search(path, visited, curLen + dst[here][next]);
        visited[next] = false;
        path.pop_back();
    }
}

double solve(){
    best = INF;
    vector<bool> visited(n, false);
    vector<int> path(1, 0);
    visited[0] = true;
    search(path, visited, 0);
    return best;
}

2. 剪枝法初步:不如最优解就当即结束

只需在 search() 函数的开头部分加入如下一行代码:

// best 初始化为INF,
// 只有在 if (path.size() == n)... 才对其进行更新;
if (best <= curLen)
    return;

3. 剪枝法进阶:利用启发式算法的剪枝法

“不如最优解”就终止搜索的剪枝法,虽然比较有用,但比起动态规划还差很远,“利用启发式方法估计剩余部分”的剪枝法就相对巧妙得多。

比如设计这样的启发式函数,会在未访问的城市相连路径中选择最短的路径相加。

int minEdge;

double simpleHeur(const vector<bool>& visited){
    double ret = minEdge[0];
    for (int i = 0; i < visited.size(); ++i)
        if (!visited[i])
            ret += minEdge[i];
                                    // 城市结点之间彼此互通
    return ret;
}

void search(vector<int>& path, vector<bool>& visited, int curLen){
    if (best <= curLen + simpleHeur(visited)) return;
    //...
}

 double solve(){
     for (int i = 0; i < n; ++i){
         minEdge[i] = INF;
         for (int j = 0; j < n; ++j){
             if (i != j)
                 minEdge[i] = min(minEdge[i], dst[i][j]);
         }
     }
 }
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

五道口纳什

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值