题目传送: UVA - 116
思路:可以定义状态为dp[i][j] 为从第i行第j列开始往后走到第n列(总共n列)的最小值(赋初始值为无穷),且状态方程很好推出来:dp[i][j] = a[i][j] + max(dp[i-1][j+1], dp[i][j+1], dp[i+1][j+1]); 最后最优解 ans = max(dp[i][1])(1<=i<=m);
不过这题难点不在这里,而是可能有多组最小值,输出字典序最小的那组;
这里要注意好递推的方向,只能从右往左递推列数,而如果从左往右递推则不能满足字典序
AC代码:
#include <cstdio> #include <cstring> #include <iostream> #include <algorithm> #define LL long long #define INF 0x7fffffff using namespace std; LL dp[15][105]; int a[15][105]; int beh[15][105]; int n, m; int main() { while(scanf("%d %d", &m, &n) != EOF) { for(int i = 1; i <= m; i++) { for(int j = 1; j <= n; j++) { scanf("%d", &a[i][j]); dp[i][j] = INF; } } memset(beh, 0, sizeof(beh)); 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++) { for(int k = -1; k <= 1; k++) { int t = i + k; if(t == 0) t = m; else if(t == m + 1) t = 1; if(a[i][j] + dp[t][j+1] < dp[i][j]) { dp[i][j] = a[i][j] + dp[t][j+1]; beh[i][j] = t; } else if(a[i][j] + dp[t][j+1] == dp[i][j] && t < beh[i][j]) { beh[i][j] = t; } } } } int ans = INF, ansi, ansj = 1; for(int i = 1; i <= m; i++) { if(dp[i][1] < ans) { ans = dp[i][1]; ansi = i; } } while(1) { if(beh[ansi][ansj] == 0) { printf("%d\n", ansi); break; } printf("%d ", ansi); ansi = beh[ansi][ansj]; ansj ++; } printf("%d\n", ans); } return 0; }
UVA - 116 - Unidirectional TSP (简单DP + 打印路径)
原文地址:http://blog.csdn.net/u014355480/article/details/45155421