您的位置:首页 > 其它

【算法竞赛入门经典】多阶段决策问题 例题9-4 UVa116

2018-02-28 19:41 519 查看

【算法竞赛入门经典】多阶段决策问题 例题9-4 UVa116

【算法竞赛入门经典】多阶段决策问题 例题9-4 UVa116
例题UVa116

分析

样例实现代码

结果

例题UVa116



Input



Output



Sample Input

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

Sample Output

1 2 3 4 4 5

16

1 2 1 5 4 5

11

1 1

19

分析

多段图是一种特殊的DAG,其结点可以划分成若干个阶段,每个阶段只由上一个阶段所

决定。

在这个题目中,每一列就是一个阶段,每个阶段都有3种决策:直行、右上和右下。

因此,所谓的状态转移方程可以写作

ans[i][j] = max(ans[rows[k]][j + 1] + da[i][j]);


其中rows[k]有三个取值,分别对应逻辑上的i-1行,i行,i+1行。

本题为了方便输出,记录了每一个每一个节点的最优解的下一列应该用哪一行。

Tip:此处利用了row数组,方便之后对特殊情况(第一行和最后一行)的修改。注意,此处可能同时满足是第一行和是最后一行,因此,两个if不可以写成if……else……

样例实现代码

#include<iostream>
#include<algorithm>
#define maxr 10+5
#define maxc 100+5
#define INF 1000000000
using namespace std;
int da[maxr][maxc];
int ans[maxr][maxc];
int nex[maxr][maxc];
int main() {
int m, n;
while (cin >> m >> n) {
for (int i = 0; i<m; i++) {
for (int j = 0; j<n; j++)
cin >> da[i][j];
}
for (int i = 0; i<m; i++) {
ans[i][n - 1] = da[i][n - 1];
}
for (int j = n - 2; j >= 0; j--) {
for (int i = 0; i<m; i++) {
int rows[3] = { i - 1,i,i + 1 };
if (i == 0)
rows[0] = m - 1;
if (i == m - 1)
rows[2] = 0;
sort(rows, rows + 3);
ans[i][j] = INF;
for (int k = 0; k<3; k++) {
if (ans[rows[k]][j + 1] + da[i][j]<ans[i][j]) {
ans[i][j] = ans[rows[k]][j + 1] + da[i][j];
nex[i][j] = rows[k];
}
}
}
}
int anss = INF, r;
for (int i = 0; i<m; i++) {
if (ans[i][0]<anss) {
anss = ans[i][0];
r = i;
}
}
cout << r + 1;
r = nex[r][0];
for (int j = 1; j<n; j++) {
cout << " " << r + 1;
r = nex[r][j];
}
cout << endl << anss << endl;
}
return 0;
}


结果

内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: