单向TSP-uva116

问题:
给你一个n行m列的整数矩形,从第一列任何一个位置出发每次往右,右上或右下走一格,最终到达最后一列。要求经过的整数之和最小,整个矩形是环形的,即第一行的上一行是最后一行,最后一行的下一行是第一行,输出路径上每列的行号,多解时输出字典序最小的。
思路:
总感觉这个题和数字三角形那个题神相似,感觉像是一个2.0版本,讲解说保证字典序最小所以采用逆序,逆向dp保证字典序最小(后继最小),正向能保证每点前驱最小。这是我没理解的。

下面是状态:f(i,j)表示走到(i,j)的最小和,则有转移方程:

f(i,j)= min(f(i+1,j+1),f(i,j+1),f(i-1,j+1));

#include<iostream>
#include<algorithm>
using namespace std;
#define MAX 100
int a[MAX][MAX];
int d[MAX][MAX];
int Next[MAX][MAX];
#define INF 9999999
void print(int m,int n) {
    int ans = INF, first = 0;
    for (int j = n - 1; j >= 0; j--) {
        for (int i = 0; i < m; i++) {
            if (j == n - 1)d[i][j] = a[i][j];
            else {
                int rows[3] = { i,i + 1,i - 1 };//设置三个方向
                if (i == m - 1)rows[1] = 0;//矩阵上下相连,考虑临界特殊值
                if (i == 0)rows[2] = m - 1;
                d[i][j] = INF;
                sort(rows, rows + 3);
                for (int k = 0; k < 3; k++) {
                    int v = d[rows[k]][j + 1] + a[i][j];
                    if (v < d[i][j]) {//比较三个方向的最小值
                        d[i][j] = v;
                        Next[i][j] = rows[k];
                    }
                }
            }
            if (j == 0 && d[i][j] < ans) {//比较列数为0时的最小值
                ans = d[i][j];
                first = i;
            }
        }
    }
    cout << first+1 << " ";
    for (int i = Next[first][0], j = 1; j < n; i = Next[i][j], j++)
        cout << i + 1 << " ";
    cout << endl;
    cout << ans;
}

int main(void) {
    int m, n;
    cin >> m >> n;
    for (int i = 0; i < m; i++)
        for (int j = 0; j < n; j++)
            cin >> a[i][j];
    print(m, n);
    system("pause");
    return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值