Unidirectional TSP UVA

来源:互联网 发布:js编辑器 编辑:程序博客网 时间:2024/06/04 01:28

题目传送门

思路:一个点可以往下延伸的状态只有三种,我们可以得出一个递推公式dp[i][j] = min(dp[i - 1][j - 1], dp[i][j - 1], dp[i + 1][j - 1]),dp[i][j]表示在(i, j)这个点上的最小值,但是我们还要求字典序最小的路径,所以我们要对着过程倒序进行,然后记录下来路径。

#include <algorithm>#include <cmath>#include <cstdio>#include <cstring>#include <iostream>#include <list>#include <map>#include <queue>#include <set>#include <stack>#include <string>#include <vector>#define MAXN 110#define MAXE 110#define INF 0x3f3f3f3f#define MOD 100003#define LL long long#define ULL unsigned long long#define pi 3.14159using namespace std;int n, m;int box[MAXN][MAXN];int dp[MAXN][MAXN];int path[MAXN][MAXN];int road[MAXN];int solve(int i, int j) {    if (i < 1 || i > n) {        return INF;    }    int &ans = dp[i][j];    if (ans < INF) {        return ans;    }    if (j == m) {        return ans = box[i][j];    }    if (i == 1) {        int num1 = solve(i, j + 1);        int num2 = solve(i + 1, j + 1);        int num3 = solve(n, j + 1);        if (num1 <= num2 && num1 <= num3) {            path[i][j] = i;            return ans = num1 + box[i][j];        } else if (num2 <= num1 && num2 <= num3) {            path[i][j] = i + 1;            return ans = num2 + box[i][j];        } else {            path[i][j] = n;            return ans = num3 + box[i][j];        }    } else if (i == n) {        int num1 = solve(1, j + 1);        int num2 = solve(i - 1, j + 1);        int num3 = solve(i, j + 1);        if (num1 <= num2 && num1 <= num3) {            path[i][j] = 1;            return ans = num1 + box[i][j];        } else if (num2 <= num1 && num2 <= num3) {            path[i][j] = i - 1;            return ans = num2 + box[i][j];        } else {            path[i][j] = i;            return ans = num3 + box[i][j];        }    } else {        int num1 = solve(i - 1, j + 1);        int num2 = solve(i, j + 1);        int num3 = solve(i + 1, j + 1);        if (num1 <= num2 && num1 <= num3) {            path[i][j] = i - 1;            return ans = num1 + box[i][j];        } else if (num2 <= num1 && num2 <= num3) {            path[i][j] = i;            return ans = num2 + box[i][j];        } else {            path[i][j] = i + 1;            return ans = num3 + box[i][j];        }    }}int main() {    std::ios::sync_with_stdio(false);    while (cin >> n >> m) {        memset(dp, 0x3f3f3f3f, sizeof(dp));        for (int i = 1; i <= n; ++i) {            for (int j = 1; j <= m; ++j) {                cin >> box[i][j];            }        }        for (int i = 1; i <= n; ++i) {            solve(i, 1);        }        int x = 1, y = 1;        int min_sum = INF;        for (int i = 1; i <= n; ++i) {            if (min_sum > dp[i][1]) {                min_sum = dp[i][1];                x = i;            }        }        int cnt = 0;        cout << x;        x = path[x][y];        y += 1;        while (y <= m) {            cout << " " << x;            x = path[x][y];            y += 1;        }        for (int i = cnt - 1; i >= 0; --i) {            if (i == 0) {                cout << road[i] << endl;            } else {                cout << road[i] << " ";            }        }        cout << endl << min_sum << endl;    }    return 0;}/* 5 6 3 4 1 2 8 6 6 1 8 2 7 4 5 9 3 9 9 5 8 4 1 3 2 6 3 7 2 8 6 4 5 6 3 4 1 2 8 6 6 1 8 2 7 4 5 9 3 9 9 5 8 4 1 3 2 6 3 7 2 1 2 3 2 2 9 10 9 10 */