Decreasing Heights
Problem Description
You are playing one famous sandbox game with the three-dimensional world. The map of the world can be represented as a matrix of size n×m, where the height of the cell ( i , j ) (i,j) (i,j) is a i , j a_{i,j} ai,j.
You are in the cell ( 1 , 1 ) (1,1) (1,1) right now and want to get in the cell ( n , m ) (n,m) (n,m). You can move only down (from the cell ( i , j ) (i,j) (i,j) to the cell ( i + 1 , j ) (i+1,j) (i+1,j)) or right (from the cell ( i , j ) (i,j) (i,j) to the cell ( i , j + 1 ) (i,j+1) (i,j+1)). There is an additional restriction: if the height of the current cell is x x x then you can move only to the cell with height x + 1 x+1 x+1.
Before the first move you can perform several operations. During one operation, you can decrease the height of any cell by one. I.e. you choose some cell ( i , j ) (i,j) (i,j) and assign (set) a i , j : = a i , j − 1 a_{i,j}:=a_{i,j}−1 ai,j:=ai,j−1. Note that you can make heights less than or equal to zero. Also note that you can decrease the height of the cell ( 1 , 1 ) (1,1) (1,1).
Your task is to find the minimum number of operations you have to perform to obtain at least one suitable path from the cell ( 1 , 1 ) (1,1) (1,1) to the cell ( n , m ) (n,m) (n,m). It is guaranteed that the answer exists.
You have to answer t independent test cases.
Input
The first line of the input contains one integer t t t ( 1 ≤ t ≤ 100 1≤t≤100 1≤t≤100) — the number of test cases. Then t test cases follow.
The first line of the test case contains two integers n n n and m m m ( 1 ≤ n , m ≤ 100 1≤n,m≤100 1≤n,m≤100) — the number of rows and the number of columns in the map of the world. The next n lines contain m integers each, where the j j j-th integer in the i i i-th line is a i , j a_{i,j} ai,j ( 1 ≤ a i , j ≤ 1 0 15 1≤a_{i,j}≤10^{15} 1≤ai,j≤1015) — the height of the cell ( i , j ) (i,j) (i,j).
It is guaranteed that the sum of n (as well as the sum of m) over all test cases does not exceed 100 ( ∑ n ≤ 100 ; ∑ m ≤ 100 ∑n≤100;∑m≤100 ∑n≤100;∑m≤100).
Output
For each test case, print the answer — the minimum number of operations you have to perform to obtain at least one suitable path from the cell ( 1 , 1 ) (1,1) (1,1) to the cell ( n , m ) (n,m) (n,m). It is guaranteed that the answer exists.
Sample Input
5
3 4
1 2 3 4
5 6 7 8
9 10 11 12
5 5
2 5 4 8 3
9 10 11 5 1
12 8 4 2 5
2 2 5 4 1
6 8 2 4 2
2 2
100 10
10 1
1 2
123456789876543 987654321234567
1 1
42
Sample Output
9
49
111
864197531358023
0
题意
一个三维地图,大小为n*m,第i行第j列的高度为
a
i
,
j
a_{i,j}
ai,j。初始在
(
1
,
1
)
(1,1)
(1,1),目标为
(
n
,
m
)
(n,m)
(n,m)。每次移动只能向下方或右方移动,同时处于高度为x的位置时,下一步只能到高度为x+1的位置。
可以进行多次操作,每次操作可以将某个位置的高度减一。求最少进行多少次操作使存在路径到达
(
n
,
m
)
(n,m)
(n,m)。
题解
对于任意一条路径,其经过的路径高度依次为
b
0
,
b
1
,
.
.
.
b
n
+
m
−
2
b_0,b_1,...b_{n+m-2}
b0,b1,...bn+m−2,使高度减一的操作最少,则起始高度应为
m
i
n
(
b
0
−
0
,
b
1
−
1
,
.
.
.
,
b
n
+
m
−
2
−
n
−
m
−
2
)
min(b_0-0,b_1-1,...,b_{n+m-2}-n-m-2)
min(b0−0,b1−1,...,bn+m−2−n−m−2)。
为了方便表述,设地图坐标从
(
0
,
0
)
(0,0)
(0,0)开始。位置
(
i
,
j
)
(i,j)
(i,j)只能对应上面的
b
i
+
j
b_{i+j}
bi+j的位置,则起始高度的可能值为
a
[
i
]
[
j
]
−
i
−
j
a[i][j]-i-j
a[i][j]−i−j。起始高度共有n*m个可能值,枚举这些值,动态规划求解到
(
n
−
1
,
m
−
1
)
(n-1,m-1)
(n−1,m−1)需要进行的最少的操作次数。
设起始高度为ps,则递推式为:
d
p
[
i
]
[
j
]
=
{
L
L
I
N
F
a
[
i
]
[
j
]
<
p
s
+
i
+
j
m
i
n
(
L
L
I
N
F
,
m
i
n
(
d
p
[
i
−
1
]
[
j
]
,
d
p
[
i
]
[
j
−
1
]
)
+
a
[
i
]
[
j
]
−
p
s
−
i
−
j
)
a
[
i
]
[
j
]
≥
p
s
+
i
+
j
dp[i][j] = \begin{cases}LLINF& a[i][j]<ps+i+j\\min(LLINF, min(dp[i-1][j],dp[i][j-1])+a[i][j]-ps-i-j) & a[i][j] \ge ps+i+j\end{cases}
dp[i][j]={LLINFmin(LLINF,min(dp[i−1][j],dp[i][j−1])+a[i][j]−ps−i−j)a[i][j]<ps+i+ja[i][j]≥ps+i+j
#include<stdio.h>
#include<iostream>
#include<cstdlib>
#include<cmath>
#include<algorithm>
#include<cstring>
#include<map>
#include<vector>
#include<queue>
#include<iterator>
#define dbg(x) cout<<#x<<" = "<<x<<endl;
#define INF 0x3f3f3f3f
#define eps 1e-6
using namespace std;
typedef long long LL;
typedef pair<int, int> P;
const int maxn = 120;
const int mod = 1000000007;
const LL llinf = 1e18;
LL a[maxn][maxn], dp[maxn][maxn];
int main()
{
int t, n, m, i, j, k;
scanf("%d", &t);
while(t--)
{
scanf("%d %d", &n, &m);
for(i=0;i<n;i++)
for(j=0;j<m;j++)
scanf("%I64d", &a[i][j]);
LL ans = llinf;
for(int a1=0;a1<n;a1++)
for(int a2=0;a2<m;a2++)
if(a[0][0] >= a[a1][a2]-a1-a2)
{
LL ps = a[a1][a2]-a1-a2;
dp[0][0] = a[0][0]-ps;
for(j=1;j<n;j++)
if(a[j][0]<ps+j || dp[j-1][0] == llinf)dp[j][0] = llinf;
else dp[j][0] = min(llinf, dp[j-1][0] + a[j][0]-ps-j);
for(j=1;j<m;j++)
if(a[0][j]<ps+j || dp[0][j-1] == llinf)dp[0][j] = llinf;
else dp[0][j] = min(llinf, dp[0][j-1] + a[0][j]-ps-j);
for(j=1;j<n;j++)
for(k=1;k<m;k++)
{
dp[j][k] = llinf;
if(a[j][k]<ps+j+k)continue;
dp[j][k] = min(dp[j][k], dp[j-1][k]+a[j][k]-ps-j-k);
dp[j][k] = min(dp[j][k], dp[j][k-1]+a[j][k]-ps-j-k);
}
ans = min(ans, dp[n-1][m-1]);
}
printf("%I64d\n", ans);
}
return 0;
}