题意:一个n*m的矩阵,每一个位置都有一定的高度,要求从(1,1)走到(n,m)并且每次移动只能向下或者向右移动,并且要求只能向比自己高度高1的位置移动。定义一个操作:执行一次可以使得任意一个格子的额高度减一,问从1,1到n,m操作的最少次数。
题解:首先一定会有一个格子的高度保持不变,设h(i,j)为格子(i,j)的高度。如果说格子在移动的过程中,格子i,j的高度不减少,那么(1,1)的高度一定是h(i,j)-i-j+2。所以可以枚举(1,1)的高度,然后如果(1,1)的高度确定了,那么整个矩阵每个格子的高度也就确定了,然后直接dp就可以了。
code:
#include<bits/stdc++.h> using namespace std; typedef long long ll; const ll N=100+7; const ll INF=1e18+7; ll arr[N][N]; vector<ll >ve; ll dp[N][N]; map<ll,bool>mp; void solve(){ ll n,m; mp.clear(); ve.clear(); cin>>n>>m; for(ll i=1;i<=n;i++){ for(ll j=1;j<=m;j++){ cin>>arr[i][j]; ve.push_back(arr[i][j]-i-j+2); } } ll ans=INF; for(ll i=0;i<ve.size();i++){ if(mp[ve[i]]) continue ; mp[ve[i]]=1; if(arr[1][1]<ve[i]) continue ; for(ll j=0;j<=n;j++){ for(ll k=0;k<=m;k++){ dp[j][k]=INF; } } dp[1][1]=arr[1][1]-ve[i]; for(ll j=1;j<=n;j++){ for(ll k=1;k<=m;k++){ if(arr[j][k]-j-k+2>=ve[i]){ dp[j][k]=min(dp[j][k],min(dp[j][k-1],dp[j-1][k])+arr[j][k]-j-k+2-ve[i]); } } } ans=min(ans,dp[n][m]); } cout<<ans<<endl; } int main(){ ll t; cin>>t; while(t--) solve(); return 0; }