标签:
1 /*
2 题意:就是从上到下,找到最短路,输出路径
3 DP+路径:状态转移方程:dp[i][j] = min (dp[i-1][j], dp[i][j-1], dp[i][j+1]) + a[[i][j]; (类似数塔问题)
4 关键在记录路径,可以用pre[x][y] = -1/0/1/2 区分,DFS回溯输出
5 详细解释:http://www.cnblogs.com/staginner/archive/2012/05/02/2479658.html
6 */
7 #include <cstdio>
8 #include <iostream>
9 #include <algorithm>
10 #include <cstring>
11 #include <cmath>
12 #include <vector>
13 #include <stack>
14 using namespace std;
15
16 const int MAXN = 1e2 + 10;
17 const int MAXM = 5e2 + 10;
18 const int INF = 0x3f3f3f3f;
19 int a[MAXN][MAXM];
20 int dp[MAXN][MAXM];
21 int pre[MAXN][MAXM];
22
23 void DFS(int x, int y)
24 {
25 if (pre[x][y] == -1) {printf ("%d", y); return ;}
26 if (pre[x][y] == 0) DFS (x-1, y);
27 else if (pre[x][y] == 1) DFS (x, y-1);
28 else DFS (x, y+1);
29
30 printf (" %d", y);
31 }
32
33 int main(void) //URAL 1029 Ministry
34 {
35 //freopen ("X.in", "r", stdin);
36
37 int n, m;
38 while (scanf ("%d%d", &n, &m) == 2)
39 {
40 memset (pre, -1, sizeof (pre));
41 memset (dp, 0, sizeof (dp));
42 for (int i=1; i<=n; ++i)
43 for (int j=1; j<=m; ++j) scanf ("%d", &a[i][j]);
44
45 for (int i=1; i<=m; ++i) {dp[1][i] = a[1][i]; pre[1][i] = -1;}
46 for (int i=2; i<=n; ++i)
47 {
48 for (int j=1; j<=m; ++j) {dp[i][j] = dp[i-1][j] + a[i][j]; pre[i][j] = 0;}
49 for (int j=2; j<=m; ++j)
50 {
51 if (dp[i][j] > dp[i][j-1] + a[i][j]) {dp[i][j] = dp[i][j-1] + a[i][j]; pre[i][j] = 1;}
52 }
53 for (int j=m-1; j>=1; --j)
54 {
55 if (dp[i][j] > dp[i][j+1] + a[i][j]) {dp[i][j] = dp[i][j+1] + a[i][j]; pre[i][j] = 2;}
56 }
57 }
58
59 int mn = INF; int x = n; int y = 1;
60 for (int i=1; i<=m; ++i)
61 {
62 if (mn > dp[n][i]) {mn = dp[n][i]; y = i;}
63 }
64 //printf ("%d\n", mn);
65 DFS (x, y); puts ("");
66 }
67
68
69 return 0;
70 }
标签:
原文地址:http://www.cnblogs.com/Running-Time/p/4494109.html