PC/UVa:111104/116
典型的分阶段决策动态规划题目,需要记录的状态为当前列当前行的最小权和。
唯一麻烦的地方在于要输出字典序最小的路径,而不是任意路径,所以从左到右的递推只能保证逆向路径字典序最小,需要改成从右到左递推才能保证正向路径字典序最小。
#include <iostream>
#include <vector>
#include <array>
#include <climits>
using namespace std;
void rfindMinWeight(const vector<vector<int>> &Matrix, const int row, const int col)
{
vector<vector<array<int, 2>>> Weight(col, vector<array<int, 2>>(row, array<int, 2>()));
for (int r = 0; r < row; r++)
{
Weight[col - 1][r][0] = Matrix[r][col - 1];
Weight[col - 1][r][1] = -1;
}
for (int c = col - 1; c > 0; c--)
{
int up, down;
for (int r = 0; r < row; r++)
{
Weight[c - 1][r][0] = Weight[c][r][0];
Weight[c - 1][r][1] = r;
up = (r == 0 ? row - 1 : r - 1);
if (Weight[c - 1][r][0] > Weight[c][up][0]){
Weight[c - 1][r][0] = Weight[c][up][0];
Weight[c - 1][r][1] = up;
}
else if (Weight[c - 1][r][0] == Weight[c][up][0]){
if (up < Weight[c - 1][r][1]) Weight[c - 1][r][1] = up;
}
down = (r == row - 1 ? 0 : r + 1);
if (Weight[c - 1][r][0] > Weight[c][down][0]){
Weight[c - 1][r][0] = Weight[c][down][0];
Weight[c - 1][r][1] = down;
}
else if (Weight[c - 1][r][0] == Weight[c][down][0]){
if (down < Weight[c - 1][r][1]) Weight[c - 1][r][1] = down;
}
Weight[c - 1][r][0] += Matrix[r][c - 1];
}
}
int minWeight = INT_MAX;
int maxRow;
for (int r = 0; r < row; r++)
{
if (Weight[0][r][0] < minWeight){
minWeight = Weight[0][r][0];
maxRow = r;
}
}
vector<int> Path;
for (int c = 0; c < col; c++)
{
Path.push_back(maxRow + 1);
maxRow = Weight[c][maxRow][1];
}
for (size_t i = 0; i < Path.size() - 1; i++)
{
cout << Path[i] << ' ';
}
cout << Path.back() << endl;
cout << minWeight << endl;
}
int main()
{
int M, N;
while (cin >> M >> N){
vector<vector<int>> Matrix(M, vector<int>(N, 0));
for (int m = 0; m < M; m++)
{
for (int n = 0; n < N; n++)
{
cin >> Matrix[m][n];
}
}
rfindMinWeight(Matrix, M, N);
}
return 0;
}
/*
5 6
3 4 1 2 8 6
6 1 8 2 7 4
5 9 3 9 9 5
8 4 1 3 2 6
3 7 2 8 6 4
5 6
3 4 1 2 8 6
6 1 8 2 7 4
5 9 3 9 9 5
8 4 1 3 2 6
3 7 2 1 2 3
2 2
9 10 9 10
*/