UVA - 116 Unidirectional TSP (单向TSP)(dp---多段图的最短路)
题意:给一个m行n列(m<=10, n<=100)的整数矩阵,从第一列任何一个位置出发每次往右,右上或右下走一格,最终到达最后一列。要求经过的整数之和最小。第一行的上一行是最后一行,最后一行的下一行是第一行。输出路径上每列的行号。多解时输出字典序最小的。
分析:
1、dp[i][j]---从第i行第j列到最后一列的最小开销。
2、列从右到左,从后一个状态可推知前一个状态的开销。
#pragma comment(linker, "/STACK:102400000, 102400000") #include<cstdio> #include<cstring> #include<cstdlib> #include<cctype> #include<cmath> #include<iostream> #include<sstream> #include<iterator> #include<algorithm> #include<string> #include<vector> #include<set> #include<map> #include<stack> #include<deque> #include<queue> #include<list> #define Min(a, b) ((a < b) ? a : b) #define Max(a, b) ((a < b) ? b : a) const double eps = 1e-8; inline int dcmp(double a, double b){ if(fabs(a - b) < eps) return 0; return a > b ? 1 : -1; } typedef long long LL; typedef unsigned long long ULL; const int INT_INF = 0x3f3f3f3f; const int INT_M_INF = 0x7f7f7f7f; const LL LL_INF = 0x3f3f3f3f3f3f3f3f; const LL LL_M_INF = 0x7f7f7f7f7f7f7f7f; const int dr[] = {0, 0, -1, 1, -1, -1, 1, 1}; const int dc[] = {-1, 1, 0, 0, -1, 1, -1, 1}; const int MOD = 1e9 + 7; const double pi = acos(-1.0); const int MAXN = 100 + 10; const int MAXT = 10000 + 10; using namespace std; int a[20][MAXN]; int dp[20][MAXN]; int path[20][MAXN];//当前位置的下一列所对应行数 int main(){ int m, n; while(scanf("%d%d", &m, &n) == 2){ memset(dp, INT_INF, sizeof dp); memset(path, 0, sizeof path); for(int i = 1; i <= m; ++i){ for(int j = 1; j <= n; ++j){ scanf("%d", &a[i][j]); } } for(int i = 1; i <= m; ++i) dp[i][n] = a[i][n]; for(int j = n - 1; j >= 1; --j){ for(int i = 1; i <= m; ++i){ int tmp[] = {i - 1, i, i + 1}; if(i == 1) tmp[0] = m; if(i == m) tmp[2] = 1; sort(tmp, tmp + 3); for(int k = 0; k < 3; ++k){ int &cur = tmp[k]; if(a[i][j] + dp[cur][j + 1] < dp[i][j]){//保证字典序最小 dp[i][j] = a[i][j] + dp[cur][j + 1]; path[i][j] = cur; } } } } int ans = INT_INF; int st = 0; for(int i = 1; i <= m; ++i){ if(dp[i][1] < ans){ ans = dp[i][1]; st = i;//第一列行数 } } printf("%d", st); for(int j = 2; j <= n; ++j){ printf(" %d", path[st][j - 1]); st = path[st][j - 1]; } printf("\n"); printf("%d\n", ans); } return 0; }