- // [解题方法]
- // 记忆化搜索(递归,子问题的结果用备忘录存起来,避免重复求解)
- // 二维nxt数组按照题意记录路径
- // dp[x][y](即dfs(x,y))表示从(x,y)走到最右边需要的最小花费
- #include <iostream>
- #include <string.h>
- #include <stdio.h>
- #include <stdlib.h>
- #include <algorithm>
- using namespace std;
- #define LL long long
- #define inf 1e16
- LL dp[11][111],w[11][111], mins, res[105];
- int r, c;
- struct point{
- int x, y;
- }nxt[11][111];
- LL dfs (int x, int y)
- {
- if (y >= c) return (dp[x][y]=w[x][y]);
- if (dp[x][y] < 1e16)
- return dp[x][y];
- int i;
- LL tp = inf;
- for (i = x-1; i <= x+1; i++)
- {
- int tr = i;
- if (tr == 0) tr = r;
- else if (tr > r) tr = 1;
- LL tmp = dfs (tr, y+1) + w[x][y];
- //更新路径(花费更小+字典序)
- if (tmp < tp || (tmp == tp && tr < nxt[x][y].x)) {
- nxt[x][y].x = tr;
- nxt[x][y].y = y+1;
- tp = tmp;
- }
- }
- return (dp[x][y]=tp);
- }
- int main()
- {
- int i, j;
- while (cin >> r >> c)
- {
- for (i = 1; i <= r; i++)
- for (j = 1; j <= c; j++)
- cin >> w[i][j], dp[i][j] = inf;
- mins = inf;
- int v;
- memset (nxt, -1, sizeof(nxt));
- for (i = 1; i <= r; i++)
- {
- LL tp = dfs (i, 1);
- if (tp < mins) {
- mins = tp;
- v = i;
- }
- }
- int tc = 1, k = 0;
- while (v > 0)
- {
- res[k++] = v;
- int tv = v;
- v = nxt[tv][tc].x;
- tc = nxt[tv][tc].y;
- }
- cout << res[0];
- for (i = 1; i < k; i++) cout << ' ' << res[i];
- cout << endl << mins << endl;
- }
- return 0;
- }
转载于:https://blog.51cto.com/daheyuan/1131711