Codeforces 1353F Decreasing Heights(dp)

题意

100*100的网格,每个格子有一个初始值,每次操作可以使一个格子的数-1,问你最少多少次操作后存在一条(只往右和下的)(从左上角到右下脚每格递增1的)路径。
格子权值至多1e15,保证答案存在

思路

路径长度显然是固定的,如果路径中有一个基准,那么每个格子应该是多少也是确定的
而路径中一定是有一个格子不操作的,因为如果所有格子都操作,显然有至少少操作n+m-1次也符合题意的答案
那么我们可以枚举这个不操作的并且在路径中的格子
由于它不操作并且在路径中,所以我们可以推出(1,1)的目标值,以及其他所有格子的目标值
进行dp即可,注意如果当前值比目标值小,这个格子是一定不在路径中的

代码

int n,m;
ll a[101][101];
ll f[101][101];
int main() {
    int t;
    scanf("%d", &t);
    mem(f,0x3f);
    while(t--){
        scanf("%d %d", &n, &m);
        for(int i = 1; i <= n; i++){
            for(int j = 1; j <= m; j++){
                scanf("%lld", &a[i][j]);
            }
        }
        ll ans = INF;
        for(int i = 1; i <= n; i++){
            for(int j = 1; j <= m; j++){
                ll bs = a[i][j]-i-j+2;
                for(int l = 1; l <= n; l++){
                    for(int r = 1; r <= m; r++){
                        if(a[l][r]>=bs+l+r-2)f[l][r]=a[l][r]-bs-l-r+2;
                        else f[l][r]=INF;
                    }
                }
                for(int l = 1; l <= n; l++){
                    for(int r = 1; r <= m; r++){
                        if(l+r!=2)f[l][r]+=min(f[l-1][r],f[l][r-1]);
                        if(f[l][r]>INF)f[l][r]=INF;
                    }
                }
                ans=min(ans,f[n][m]);
            }
        }
        printf("%lld\n",ans);

    }
    return 0;
}
posted @ 2020-05-16 11:45  wrjlinkkkkkk  阅读(230)  评论(0编辑  收藏  举报