UVA - 116 Unidirectional TSP(dp+多段图的最短路)

题意:
给一个n行m列的整数矩阵,从第一列任何一个位置出发每次往右、右上或右下走一格,最终到达最后一列。要求经过的整数之和最小。整个矩阵是环形的,即第一行的上一行是最后一行,最后一行的下一行是第一行。
输出路径上每行的行号。多解时输出字典序最小的。
解析:

从后往前逆推,dp[i][j]记录,到(i,j)当前整数和最小,再开一个next数组用于保存路径。

#include <cstring>
#include <cstdio>
#include <algorithm>
using namespace std;
const int N = 105;
const int INF = 0x3f3f3f3f;
int grid[N][N];
int next[N][N], dp[N][N];
int m,n;
int main() {
	while( scanf("%d%d",&n,&m) != EOF) {
		for(int i = 0; i < n; i++) {
			for(int j = 0; j < m; j++) {
				scanf("%d",&grid[i][j]);
			}
		}
		memset(dp,0,sizeof(dp));
		int ans = INF , first = 0;
	
		for(int j = m-1; j >= 0; j--) { //逆推
			for(int i = 0; i < n; i++) {
				if(j == m-1) {
					dp[i][j] = grid[i][j];
				}else {
					int rows[3] = {i-1, i, i+1};
					if(i == 0) { //边界
						rows[0] = n-1;
					}
					if(i == n-1) {
						rows[2] = 0;
					}
					sort(rows,rows+3);
					dp[i][j] = INF;
					for(int k = 0; k < 3; k++) { //求当前所花费的最少步数
						int v = dp[rows[k]][j+1] + grid[i][j];
						if(v < dp[i][j]) {
							dp[i][j] = v;
							next[i][j] = rows[k];
						}
					}
				}
				if(j == 0 && dp[i][j] < ans) {
					ans = dp[i][j];
					first = i;
				}
			}
		}
		printf("%d",first+1);
		int i = next[first][0] , j = 1;
		while( j < m) {
			printf(" %d",i+1);
			i = next[i][j];
			j++;
		}
		printf("\n%d\n",ans);
	}
	return 0;
}


你可能感兴趣的:(uva,TSP,Unidirectional,116)