Description
HB要办个签证,办证处是一座 M 层的大楼,每层楼都有 N 个办公室,编号为1..N,每个办公室有一个签证员,签证需要让第 M 层的某个签证员盖章才有效。每个签证员都要满足下面三个条件之一才会给HB盖章:
- 这个签证员在1楼。
- HB的签证已经给这个签证员的正楼下(房间号相同)的签证员盖过章了。
- HB的签证已经给这个签证员的相邻房间(房间号相差1,楼层相同)的签证员盖过章了。
每个签证员盖章都要收取一定费用,这个费用不超过1000000000。找出费用最小的盖章路线,使签证生效。
Input
第1行两个整数 M 和 N 。 接下来M行每行 N 个整数,第i行第j个数表示第i层的第j个签证员收取的费用。
Output
输出最小的费用。
Sample Input 1
3 4
10 10 1 10
2 2 2 10
1 10 10 10
Sample Output 1
8
Hint
1<=M<=100,1<=N<=500
乍一看很简单,只需要设状态函数f(i,j)表示到第i层第j个房间需要的最小花费,转移方程:
\(f(i,j)=min(f(i-1,j),f(i,j-1),f(i,j+1))+a[i][j]\)
其中a[i][j]为当前房间的花费。
初始化
\(f(i,j)=inf\)
\(f(1,j)=a[1][j]|1<=j<=m\)
但是如果每一层这样去转移,无论是从左向右计算还是从右向左计算都有后效性,因为如果从左向右更新,那么计算f(i,j)时用到的f(i,j+1)还没有更新过,会引起错误
解决方法是每一层先从左向右走用f(i,j-1)更新f(i,j),走完这层再从右向左走用f(i,j+1)更新f(i,j),保证了计算时用到的数都不是未知的。
\(Ans=min(f(n,j)|1<=j<=m)\)
我的代码里是从上向下走的,区别不大
#include
#include
#include
#include
#include
#include
#include
#include
#include