题意
给出一个
n
∗
m
n*m
n∗m的矩阵,第i行第j列的高度为
a
i
,
j
a_{i,j}
ai,j,每次只能向下或向右,并且移动的位置的高度差只能为
1
1
1.
你可以在走之前给一些位置高度
−
1
-1
−1,问最少多少次操作能让你找到一条路径。
思路
对于初始高度
h
h
h,我们发现
a
i
,
j
a_{i,j}
ai,j的高度是
h
+
(
i
−
1
)
+
(
j
−
1
)
h+(i-1)+(j-1)
h+(i−1)+(j−1)
于是有转移方程
d
p
[
i
]
[
j
]
=
{
i
n
f
a
[
i
]
[
j
]
<
h
+
(
i
−
1
)
+
(
j
−
1
)
m
i
n
(
d
p
[
i
−
1
]
[
j
]
,
d
p
[
i
]
[
j
−
1
]
)
+
a
[
i
]
[
j
]
−
(
h
+
(
i
−
1
)
+
(
j
−
1
)
)
a
[
i
]
[
j
]
≥
h
+
(
i
−
1
)
+
(
j
−
1
)
dp[i][j] = \begin{cases} inf & a[i][j] < h+(i-1)+(j-1) \\ min(dp[i-1][j],dp[i][j-1]) + a[i][j] - (h+(i-1)+(j-1))& a[i][j] \ge h+(i-1)+(j-1) \end{cases}
dp[i][j]={infmin(dp[i−1][j],dp[i][j−1])+a[i][j]−(h+(i−1)+(j−1))a[i][j]<h+(i−1)+(j−1)a[i][j]≥h+(i−1)+(j−1)
代码
#include<bits/stdc++.h>
#define int long long
#define N 105
#define rep(i,a,n) for (int i=a;i<=n;i++)
#define per(i,a,n) for (int i=n;i>=a;i--)
#define inf 0x3f3f3f3f3f3f3f3f
#define pb push_back
#define mp make_pair
#define lowbit(i) ((i)&(-i))
#define VI vector<int>
using namespace std;
int t,n,m,a[N][N],dp[N][N];
int solve(int x){
memset(dp,0x3f,sizeof dp);
if(a[1][1] < x) return inf;
else dp[1][1] = a[1][1]-x;
rep(i,1,n){
rep(j,1,m){
if(i==1&&j==1) continue;
int h = x+(i-1)+(j-1);
if(a[i][j] < h) continue;
dp[i][j] = min(dp[i-1][j],dp[i][j-1])+a[i][j]-h;
}
}
return dp[n][m];
}
signed main(){
//freopen(".in","r",stdin);
//freopen(".out","w",stdout);
ios::sync_with_stdio(0);
cin.tie(0);
cin>>t;
while(t--){
cin>>n>>m;int ans = inf;
rep(i,1,n){
rep(j,1,m) cin>>a[i][j];
}
rep(i,1,n){
rep(j,1,m){
int h = a[i][j] - (i-1)-(j-1);
ans = min(ans,solve(h));
}
}
cout << ans << endl;
}
return 0;
}