最平坦的路线题解

该题目描述了一个城市地图的旅行路径规划问题,要求找到从左上角到右下角的一条路径,使得经过的点的高度方差最小。输入包含地图的高度数据,输出为最小方差乘以(n+m-1)^2后的值。解决方案通过动态规划和枚举平均高度来计算最小方差,总时间复杂度为O(50nm(n+m))。
摘要由CSDN通过智能技术生成

题目描述

现有一个城市的地图,地图是一个 n × m n\times m n×m的矩形,现在要在这个城市中旅行,旅行的起点左上角坐标为 ( 1 , 1 ) (1,1) (1,1),终点右下角坐标为 ( n , m ) (n,m) (n,m)。地图上记录了每一个点的高度,坐标为 ( x , y ) (x,y) (x,y)的位置,高度为 h x , y h_{x,y} hx,y。每次只能向右或向下,不能走出城市,只能在整数点转弯。请你计算出一条路线,使得经过的点的高度的方差最小。输出最小的方差乘 ( n + m − 1 ) 2 (n+m-1)^2 (n+m1)2后的值。

方差的定义:对于 k k k个整数 x 1 , x 2 , ⋯   , x k x_1,x_2,\cdots,x_k x1,x2,,xk,这 k k k个数的方差为 S 2 = ( x 1 − x ‾ ) 2 + ( x 2 − x ‾ ) 2 + ⋯ + ( x k − x ‾ ) 2 k S^2=\frac{(x_1-\overline{x})^2+(x_2-\overline{x})^2+\cdots+(x_k-\overline{x})^2}{k} S2=k(x1x)2+(x2x)2++(xkx)2,其中 x ‾ \overline{x} x为这 k k k个整数的平均值,即 x ‾ = x 1 + x 2 + ⋯ + x k k \overline{x}=\frac{x_1+x_2+\cdots+x_k}{k} x=kx1+x2++xk

输入格式

第一行输入 n , m n,m n,m
下面 n n n行,每行 m m m个数,第 i i i行第 j j j列为 h i , j h_{i,j} hi,j

输出格式

输出最小的方差乘 ( n + m − 1 ) 2 (n+m-1)^2 (n+m1)2后的值

样例输入
2 2
1 2
3 4

样例输出

14

数据范围

对于 30 % 30\% 30%的数据, 1 ≤ n , m ≤ 10 1\leq n,m\leq 10 1n,m10
对于 50 % 50\% 50%的数据, 1 ≤ n , m ≤ 20 1\leq n,m\leq 20 1n,m20
对于 100 % 100\% 100%的数据, 1 ≤ n , m ≤ 50 , 0 ≤ h x , y ≤ 50 1\leq n,m\leq 50,0\leq h_{x,y}\leq 50 1n,m50,0hx,y50


题解

可以看出要经过的点的数量为 n + m − 1 n+m-1 n+m1,为方便表述,令 k = n + m − 1 k=n+m-1 k=n+m1

数据范围比较小,平均数又不好处理,我们可以考虑枚举平均数。因为 0 ≤ x ‾ ≤ 50 0\leq \overline{x} \leq 50 0x50,所以 0 ≤ k ⋅ x ‾ ≤ 50 k 0\leq k\cdot\overline{x} \leq 50k 0kx50k,且 k ⋅ x ‾ k\cdot\overline{x} kx为整数。于是我们就可以枚举 k ⋅ x ‾ k\cdot\overline{x} kx,再计算最大值。

将要求的式子拆一下, k 2 × S 2 = k 2 × ( x 1 − x ‾ ) 2 + ( x 2 − x ‾ ) 2 + ⋯ + ( x k − x ‾ ) 2 k = k ( ( ∑ x i 2 ) − 2 x ‾ ( ∑ x i ) + k x ‾ 2 ) k^2\times S^2=k^2\times\frac{(x_1-\overline{x})^2+(x_2-\overline{x})^2+\cdots+(x_k-\overline{x})^2}{k}=k((\sum x_i^2)-2\overline{x}(\sum x_i)+k\overline{x}^2) k2×S2=k2×k(x1x)2+(x2x)2++(xkx)2=k((xi2)2x(xi)+kx2),在 x ‾ \overline{x} x一定的情况下, x i x_i xi的贡献为 k ( x i 2 − 2 x ‾ x i ) = k x i 2 − 2 k x ‾ x i k(x_i^2-2\overline{x}x_i)=kx_i^2-2k\overline{x}x_i k(xi22xxi)=kxi22kxxi

设当前枚举的 k ⋅ x ‾ k\cdot\overline{x} kx值为 t t t,设 f i , j f_{i,j} fi,j表示从 ( 1 , 1 ) (1,1) (1,1) ( i , j ) (i,j) (i,j)的最小的贡献,则可以列出转移式
f i , j = min ⁡ ( f i − 1 , j , f i , j − 1 ) + k ⋅ h i , j 2 + 2 t ⋅ h i , j f_{i,j}=\min(f_{i-1,j},f_{i,j-1})+k\cdot h_{i,j}^2+2t\cdot h_{i,j} fi,j=min(fi1,j,fi,j1)+khi,j2+2thi,j

那么答案为对于每一个 t t t f n , m + t 2 f_{n,m}+t^2 fn,m+t2的最小值。

那如果这 k k k个数的平均值乘 k k k t t t不相等怎么办,不就多算了几种情况吗?

会多一些情况,但不影响答案。设 t = k x ‾ + a ( a ≠ 0 ) t=k\overline{x}+a(a\neq0) t=kx+a(a=0)
此次计算的答案: k ( ∑ x i 2 ) − 2 t ( ∑ x i ) + t 2 = k ( ∑ x i 2 ) − 2 ( k x ‾ + a ) ( k x ‾ ) + ( k x ‾ + a ) 2 k(\sum x_i^2)-2t(\sum x_i)+t^2=k(\sum x_i^2)-2(k\overline{x}+a)(k\overline{x})+(k\overline{x}+a)^2 k(xi2)2t(xi)+t2=k(xi2)2(kx+a)(kx)+(kx+a)2

实际上的答案: k ( ∑ x i 2 ) − 2 k x ‾ ( ∑ x i ) + k 2 x ‾ 2 = k ( ∑ x i 2 ) − 2 ( k x ‾ ) 2 + k 2 x ‾ 2 k(\sum x_i^2)-2k\overline{x}(\sum x_i)+k^2\overline{x}^2=k(\sum x_i^2)-2(k\overline{x})^2+k^2\overline{x}^2 k(xi2)2kx(xi)+k2x2=k(xi2)2(kx)2+k2x2

上下做差得 − 2 a k x ‾ + 2 a k x ‾ + a 2 = a 2 > 0 -2ak\overline{x}+2ak\overline{x}+a^2=a^2>0 2akx+2akx+a2=a2>0,所以当 t ≠ k x ‾ t\neq k\overline{x} t=kx时,得出的答案会更大,而这个答案一定会被 t = k x ‾ t=k\overline{x} t=kx时的答案覆盖,所以这是可行的。

枚举 t t t O ( 50 ( n + m ) ) O(50(n+m)) O(50(n+m)),每次DP都是 O ( n m ) O(nm) O(nm),所以总时间复杂度为 O ( 50 n m ( n + m ) ) O(50nm(n+m)) O(50nm(n+m))

code

#include<bits/stdc++.h>
using namespace std;
int n,m,k;
long long ans=1e18,a[55][55],f[55][55];
int main()
{
	scanf("%d%d",&n,&m);k=n+m-1;
	for(int i=1;i<=n;i++){
		for(int j=1;j<=m;j++){
			scanf("%lld",&a[i][j]);
		}
	}
	for(int o=0;o<=5000;o++){
		f[1][1]=a[1][1]*a[1][1]*k-2*a[1][1]*o;
		for(int i=1;i<=n;i++){
			for(int j=1;j<=m;j++){
				if(i!=1||j!=1) f[i][j]=1e18;
				if(i>1) f[i][j]=min(f[i][j],f[i-1][j]+a[i][j]*a[i][j]*k-2*a[i][j]*o);
				if(j>1) f[i][j]=min(f[i][j],f[i][j-1]+a[i][j]*a[i][j]*k-2*a[i][j]*o);
			}
		}
		ans=min(ans,f[n][m]+o*o);
	}
	printf("%lld",ans);
	return 0;
}
  • 3
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值