AT_abc210_d [ABC210D] National Railway 的题解

AT_abc210_d [ABC210D] National Railway 的题解

洛谷传送门

AT传送门

题目大意

给你一个 n × m n\times m n×m 大小的地点,问你需要选择两个地点建地点站,并在其之间建立轨道,问最小花费。

思路

根据题意,实际上建立轨道的花费相当于是它们的曼哈顿距离 × c \times c ×c,所以如果我们建好了一个站,那么相当于我可以行走到下一个地点再建一个站,所以我们可以先记录好前半部分的最小花费。我们可以用 d p [ i ] [ j ] dp[i][j] dp[i][j] 来表示已经建好了一个地铁站,且已经走到了 ( i , j ) (i,j) (i,j),为了考虑全面,我们遍历的方向实际上就是东北和东南方向。所以我们要分两次来跑,对于东南方向,状态转移方程易知: d p [ i ] [ j ] = { a i j , d p [ i − 1 ] [ j ] + c , d p [ i ] [ j − 1 ] + c } dp[i][j] = \{a_{ij},dp[i-1][j]+c,dp[i][j-1]+c\} dp[i][j]={ aij,dp[i1][j]+c,dp[i][j1]+c} 那么我们处理好 d p dp dp 数组之后,还有一点就是如何确定最后一个地铁站建在哪最优,哪很明显,我们直接遍历 d p dp dp 数组再枚举我们建立的地铁站即可。

代码

#include <bits/stdc++.h>
#define lowbit(x) x & (-x)
#define endl "\n"
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
namespace fastIO {
    
    
	inline int read() {
    
    
		register int x = 0, f = 1;
		register char c = getchar();
		while (c < '0' || c > '9') {
    
    
			if(c == '-') f = -1;
			c = getchar();
		}
		while (c >= '0' && c <= '9') x = x * 10 + c - '0', c = getchar();
		return x * f;
	}
	inline void write(int x) {
    
    
		if(x < 0) putchar('-'), x = -x;
		if(x > 9) write(x / 10);
		putchar(x % 10 + '0');
		return;
	}
}
using namespace fastIO;
const ll INF = 0x3f3f3f3f3f3f3f;
int n, m, c;
ll a[1005][1005], dp[1005][1005], ans[1005][1005];
int main() {
    
    
	//freopen(".in","r",stdin);
	//freopen(".out","w",stdout);
    n = read(), m = read(), c = read();
    for(int i = 1; i <= n; i ++) {
    
    
        for(int j = 1; j <= m; j ++) {
    
    
            scanf("%lld", &a[i][j]);
        }
    }
    fill(dp[0], dp[0] + 1005 * 1005, INF);
    fill(ans[0], ans[0] + 1005 * 1005, INF);
    for(int i = 1; i <= n; i ++) {
    
    
        for(int j = 1; j <= m; j ++) {
    
    
            dp[i][j] = min(a[i][j], min(dp[i - 1][j], dp[i][j - 1]) + c);
        }
    }
    ll minn = INF;
    for(int i = 1; i <= n; i ++) {
    
    
        for(int j = 1; j <= m; j ++) {
    
    
            ans[i][j] = min(dp[i - 1][j], dp[i][j - 1]) + c + a[i][j];
            minn = min(ans[i][j], minn);
        }
    }
    for(int i = n; i >= 1; i --) {
    
    
        for(int j = 1; j <= m; j ++) {
    
    
            dp[i][j] = min(a[i][j], min(dp[i + 1][j], dp[i][j - 1]) + c);
        }
    }
    for(int i = 1; i <= n; i ++) {
    
    
        for(int j = 1; j <= m; j ++) {
    
    
            ans[i][j] = min(dp[i + 1][j], dp[i][j - 1]) + c + a[i][j];
            minn = min(ans[i][j], minn);
        }
    }
    printf("%lld\n", minn);
	return 0;
}

猜你喜欢

转载自blog.csdn.net/ZH_qaq/article/details/130458137