ABC 210 D - National Railway

D - National Railway

矩阵DP,拆绝对值

设向下为 x 正方向,向右为 y 正方向

设两个点为 (x1,y1),(x2,y2), 代价为 Ax1y1+Ax2y2+|x1x2|+|y1y2|

想办法拆掉绝对值

  1. (x2,y2)(x1,y1) 右下方,则 |x1x2|+|y1y2|=(x2+y2)(x1+y1)

    cost=Ax2y2+(x2+y2)+(Ax1y1(x1+y1))

  2. (x2,y2)(x1,y1) 左下方,则 |x1x2|+|y1y2|=(x2y2)(x1y1)

    cost=Ax2y2+(x2y2)+(Ax1y1(x1y1))

在第一种方案中,设 f[i][j](i,j) 为右下角的小矩阵中,Axy(x+y) 的最小值

f[i][j]=min(f[i1][j],f[i][j1],Aij(i+j))

所以枚举 (i,j) 作为 (x2,y2), (x1,y1) 的最小代价就是 f[i][j](注意先更新 f[i][j]=min(f[i1][j],f[i][j1]) 后求出当前的答案,再更新 f[i][j]=min(f[i][j],Aij(i+j)), 因为 (x1,y1)(x2,y2)

#include <iostream>
#include <algorithm>
#include <cstring>
#include <vector>
#include <cmath>

using namespace std;
#define endl "\n"

typedef long long ll;
typedef pair<int, int> PII;

const int N = 1e3 + 10;
const ll INF = 0x3f3f3f3f3f3f3f3f;
int n, m;
ll c, a[N][N];
ll f[N][N];

ll solve1()
{
	ll ans = INF;
	memset(f, 0x3f, sizeof f);
	for (int i = 1; i <= n; i++)
	{
		for (int j = 1; j <= m; j++)
		{
			f[i][j] = min(f[i-1][j], f[i][j-1]);
			ans = min(ans, a[i][j] + c * (i + j) + f[i][j]);
			f[i][j] = min(f[i][j], a[i][j] - c * (i + j));
		}
	}
	return ans;
}

ll solve2()
{
	ll ans = INF;
	memset(f, 0x3f, sizeof f);
	for (int i = 1; i <= n; i++)
	{
		for (int j = m; j >= 1; j--)
		{
			f[i][j] = min(f[i-1][j], f[i][j+1]);
			ans = min(ans, a[i][j] + c * (i - j) + f[i][j]);
			f[i][j] = min(f[i][j], a[i][j] - c * (i - j));
		}
	}
	return ans;
}
int main()
{
	ios::sync_with_stdio(0), cin.tie(0), cout.tie(0);
	cin >> n >> m >> c;
	for (int i = 1; i <= n; i++)
		for (int j = 1; j <= m; j++)
			cin >> a[i][j];
		
	ll ans = min(solve1(), solve2());
	cout << ans << endl;
    return 0;
}
posted @   hzy0227  阅读(31)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 25岁的心里话
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· 闲置电脑爆改个人服务器(超详细) #公网映射 #Vmware虚拟网络编辑器
· 一起来玩mcp_server_sqlite,让AI帮你做增删改查!!
· 零经验选手,Compose 一天开发一款小游戏!
点击右上角即可分享
微信分享提示