F. Decreasing Heights(思维,dp)

题:https://codeforces.com/contest/1353/problem/F

题意:给定n*m的矩形,每个位置都有aij的高度,位于某一位置你只能向下或向右走,且得满足下一个格子高度y和当前格子高度x条件:y==x+1;

分析:我们可以把题目条件转化为y==x,那么就可以通过确定一个高度dp地从[1,1]往下找一个权值和最小路径。这个转化,就对于每一个位置减去(i+j-2)即可;

   dp过程:假设经过某条路径,那么这条路径上的某一高度权值一定不变,

#include<cstdio>
#include<iostream>
#include<vector>
#include<algorithm>
#include<unordered_map>
using namespace std;
#define pb push_back
typedef long long ll;
const int M=1e2+2;
const ll INF=1e18;
unordered_map<ll,int>mp;
ll dp[M][M],a[M][M];
int main(){
    int t;
    scanf("%d",&t);
    while(t--){
        int n,m;
        scanf("%d%d",&n,&m);
        for(int i=1;i<=n;i++)
            for(int j=1;j<=m;j++){
                scanf("%lld",&a[i][j]);
                a[i][j]-=(i+j-2);///让题目条件转化为走的路径要高度相同
            }
        mp.clear();
        ll ans=INF;
        for(int x=1;x<=n;x++)
            for(int y=1;y<=m;y++){
                if(mp[a[x][y]])
                    continue;
                mp[a[x][y]]=1;
                for(int i=1;i<=n;i++)
                    for(int j=1;j<=m;j++)
                        dp[i][j]=INF;
                if(a[1][1]-a[x][y]<0)
                    continue;
                dp[1][1]=a[1][1]-a[x][y];
                for(int i=1;i<=n;i++)
                    for(int j=1;j<=m;j++){
                        if(a[i+1][j]>=a[x][y])
                            dp[i+1][j]=min(dp[i+1][j],dp[i][j]+(a[i+1][j]-a[x][y]));
                        if(a[i][j+1]>=a[x][y])
                            dp[i][j+1]=min(dp[i][j+1],dp[i][j]+(a[i][j+1]-a[x][y]));
                    }

                ans=min(ans,dp[n][m]);
            }
        printf("%lld\n",ans);
    }
    return 0;
}
View Code

 

posted @ 2020-05-20 15:58  starve_to_death  阅读(162)  评论(0编辑  收藏  举报