#include <iostream>
#include <algorithm>
#include <cstring>
using namespace std;
const int M = 11;
const int N = 110;
const int INF = (1<<30);
int main()
{
int n, m, first;
int ans;
int a[M][N], next[M][N], dp[M][N];
while(cin>>m>>n) { // 死循环
memset(a, 0, sizeof(a));
memset(next, 0, sizeof(next));
memset(dp, 0, sizeof(dp));
ans = INF;
// cin >> m >> n;
for (int i = 0; i < m; i++) {
for (int j = 0; j < n; j++) {
cin >> a[i][j];
}
}
for (int j = n - 1; j >= 0; j--) { // 从最后一列往前推
for (int i = 0; i < m; i++) {
if (n - 1 == j) { // 如果是最后一列
dp[i][j] = a[i][j];
}
else {
dp[i][j] = INF;
int row[3]; //下 一步是哪一行
row[0] = i; // 本行
row[1] = i == 0 ? m - 1 : i - 1; // 左上
row[2] = i == m - 1 ? 0 : i + 1; // 右下
sort(row, row + 3); // 行号字典序排列
for (int k = 0; k < 3; k++) {
int tmp = dp[row[k]][j + 1] + a[i][j]; // 状态转移方程
if (tmp < dp[i][j]) {
dp[i][j] = tmp;
next[i][j] = row[k]; // next[i][j] 表示这一列最优路径上的行号
}
}
}
if (j == 0 && dp[i][j] < ans) {
ans = dp[i][j];
first = i; // first 表示的是 第一列最优路径的行号,即起始位置
}
}
}
cout << first + 1 ;
int j = 1;
for (int i = next[first][0]; j < n; i = next[i][j], j++) // i表示行号; 思考为什么j++ 要放到 i = next[i][j]的后面?
cout << " " << i + 1;
cout << endl;
cout << ans << endl;
}
return 0;
}
洛谷,UVA116, 简单多段决策dp
最新推荐文章于 2021-09-23 17:54:39 发布