uva 116 - Unidirectional TSP(数字三角)

题目连接:116 Unidirectional TSP


题目大意:给出一个n * m的矩阵, 可以看成是 n 棵横着放的三叉树, 要求求所有路径中权值最小的, 并输出字典序最小的方案。


解题思路:状态转移方程:num[i][j] = max ( num[i - 1][j + 1], num[i - 1][j + 1], num[i - 1][j + 1]), 注意上下边界是相连,

然后rec[i][j]记录最优解选择的方向,整个的处理方向需要从前往后, 因为字典序要最小。


#include <stdio.h>
#include <string.h>
const int N = 105;
int min (int a, int b) {    return a < b ? a : b; }

int n, m, sum, ans[N], num[N][N], rec[N][N];

void solve() {
    int k, t, a, i, c;
    memset(rec, -1, sizeof(rec));
    for (int j = m - 1; j > 0; j--) {
	k = j + 1;
	for (int i = 1; i <= n; i++) {
	    a = i - 1;
	    if (a == 0) a = n;
	    c = i + 1;
	    if (c == n + 1)	c = 1;
	    if (num[a][k] <= num[i][k] && num[a][k] <= num[c][k]) {
		num[i][j] += num[a][k];
		t = a;
		if (num[a][k] == num[i][k]) t = min(t, i);
		if (num[a][k] == num[c][k]) t = min(t, c);
		rec[i][j] = t;
	    }
	    else if (num[i][k] <= num[a][k] && num[i][k] <= num[c][k]) {
		num[i][j] += num[i][k];
		t = i;
		if (num[i][k] == num[a][k]) t = min(t, a);
		if (num[i][k] == num[c][k]) t = min(t, c);
		rec[i][j] = t;
	    }
	    else {
		num[i][j] += num[c][k];
		t = c;
		if (num[c][k] == num[a][k]) t = min(t, a);
		if (num[c][k] == num[i][k]) t = min(t, i);
		rec[i][j] = t;
	    }
	}
    }

    sum = 1 << 30, t = 0;
    for (int i = 1; i <= n; i++) {
	if (num[i][1] < sum) {
	    sum = num[i][1];
	    t = i;
	}
    }
    
    for (int i = 1; i < m; i++) {
	ans[i] = t;
	t = rec[t][i];
    }
    ans[m] = t;
}

int main() {
    while (scanf("%d%d", &n, &m) == 2) {
	// Read;
	memset(num, 0, sizeof(num));
	for (int i = 1; i <= n; i++) {
	    for (int j = 1; j <= m; j++)
		scanf("%d", &num[i][j]);
	}

	solve();
	for (int i = 1; i < m; i++)
	    printf("%d ", ans[i]);
	printf("%d\n%d\n", ans[m], sum);
    }
    return 0;
}

你可能感兴趣的:(uva 116 - Unidirectional TSP(数字三角))