UVa-116 Unidirectional TSP 单向旅行商

题目

https://vjudge.net/problem/uva-116

分析

d[i][j]为从(i,j)到最后一列的最小开销,则d[i][j]=a[i][j]+max(d[i+1][j+1],d[i-1][j+1])
参考数字三角形,用逆推的方法,先确定最后一列d[i][n-1]=a[i][n-1],再确定n-2列,此时d[i][n-2] = a[i][n-2]+min(d[i][n-1],d[i-1][n-1],d[i+1][n-1])
最终推出全部的d[i][j]后,第一列最小的d就是答案.

另外要求打印路径,因此建立一个数组next1[i][j],保存结点i,j之后的结点.
在逆推的时候,如果d[rows[k]][j+1]+a[i][j] < d[i][j] 就更新next1[i][j]=rows[k]

AC代码

#include "bits/stdc++.h"
using namespace std;
#define inf 0x3f3f3f3f
int main(int argc, char const *argv[])
{
    ios::sync_with_stdio(false);
    int a[150][150], d[150][150], next1[150][150];
    int ans = inf, first = 0, m, n, i, j, k;
    while (cin >> m && m != - 1) {
        cin >> n;
        ans = inf;

        //d[i][j]表示从i, j开始走可以经过的最小整数和
        //因此可以知道最后一列d[i][n-1] = a[i][n-1]
        for(i=0;i<m;i++)
            for(j=0;j<n;j++)
                cin >> a[i][j];

        for (i = 0; i < m; i++)
            d[i][n - 1] = a[i][n - 1];  //初始化最后一列

        for (j = n - 2; j >= 0; j--) {
            for (i = 0; i < m; i++) {
                int rows[3] = {i, i - 1, i + 1};
                if (i == 0) rows[1] = m - 1; //第一行与最后一行相邻
                if (i == m - 1) rows[2] = 0;
                sort(rows, rows + 3);
                d[i][j] = inf;
                for (k = 0; k < 3; k++) {
                    int v = a[i][j] + d[rows[k]][j + 1];
                    if(v < d[i][j]){
                        d[i][j] = v;//更新最短路
                        next1[i][j] = rows[k];//记录路径,只记录行,因为列是递增的
                    }
                }
                if(j ==0 && d[i][j] < ans){
                    ans = d[i][j];
                    first = i;
                }
            }
        }
        //因为上面是从n - 2列开始, 所以只有一列是要单独处理
        if(n==1){
            for(i=0;i<m;i++){
                if(ans > a[i][0]){
                    ans = a[i][0];
                    first = i;
                }
            }
        }


        cout << first + 1;
        for(int i=next1[first][0], j=1; j<n; i = next1[i][j],j++){
            cout << ' ' << i+1;
        }
        cout << endl << ans << endl;
    }
    return 0;
}

转载于:https://www.cnblogs.com/lepeCoder/p/UVa-116.html

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值