1 /* 2 题意:从上到下,找最短路径,并输出路径 3 DP:类似数塔问题,上一行的三个方向更新dp,路径输出是关键 4 */ 5 #include <cstdio> 6 #include <algorithm> 7 #include <iostream> 8 #include <cstring> 9 #include <cmath> 10 #include <string> 11 #include <vector> 12 #include <queue> 13 #include <map> 14 #include <set> 15 #include <ctime> 16 #include <cstdlib> 17 using namespace std; 18 19 const int MAXN = 1e2 + 10; 20 const int INF = 0x3f3f3f3f; 21 int a[MAXN][MAXN]; 22 int dp[MAXN][MAXN]; 23 int pre[MAXN][MAXN]; 24 25 void print(int x, int y) 26 { 27 if (x == 1) 28 { 29 printf ("%d", y); return ; 30 } 31 print (x - 1, pre[x][y]); 32 printf (" %d", y); 33 } 34 35 int main(void) //HDOJ 5092 Seam Carving 36 { 37 //freopen ("C.in", "r", stdin); 38 39 int n, m, t, cas = 0; 40 scanf ("%d", &t); 41 while (t--) 42 { 43 scanf ("%d%d", &n, &m); 44 for (int i=1; i<=n; ++i) 45 for (int j=1; j<=m; ++j) scanf ("%d", &a[i][j]); 46 memset (pre, 0, sizeof (pre)); 47 48 for (int i=2; i<=n; ++i) 49 for (int j=1; j<=m; ++j) dp[i][j] = INF; 50 for (int i=1; i<=m; ++i) dp[1][i] = a[1][i]; 51 52 for (int i=2; i<=n; ++i) 53 { 54 for (int j=m; j>=1; --j) 55 { 56 for (int k=1; k>=-1; --k) 57 { 58 if (j + k < 1 || j + k > m) continue; 59 if (dp[i][j] > dp[i-1][j+k] + a[i][j]) 60 { 61 dp[i][j] = dp[i-1][j+k] + a[i][j]; 62 pre[i][j] = j + k; 63 } 64 } 65 } 66 } 67 68 int k = m; int mn = dp[n][m]; 69 for (int i=m-1; i>=1; --i) 70 { 71 if (mn > dp[n][i]) {mn = dp[n][i]; k = i;} 72 } 73 74 printf ("Case %d\n", ++cas); 75 print (n, k); 76 puts (""); 77 } 78 79 return 0; 80 } 81 82 /* 83 Case 1 84 2 1 1 2 85 Case 2 86 3 2 1 1 2 1 87 */
时间: 2024-10-19 13:36:02