【ybtoj高效进阶 21283】优秀路线(数学)(DP)

优秀路线

题目链接:ybtoj高效进阶 21283

题目大意

给你一个二维网格,要你选一条左上到右下的路径,只能向右向下走,使得路径上的数方差最小。

思路

方差嘛,直接开拆!
( x i − x 0 ) 2 (x_i-x_0)^2 (xix0)2
∑ x i 2 − ∑ 2 x i x 0 + n x 0 2 \sum x_i^2-\sum2x_ix_0+nx_0^2 xi22xix0+nx02
( x 0 = ∑ x i / n ) (x_0=\sum x_i/n) (x0=xi/n)
∑ x i 2 − ∑ 2 x i x 0 + ∑ x i x 0 \sum x_i^2-\sum2x_ix_0+\sum x_i x_0 xi22xix0+xix0
∑ x i 2 − ∑ x i x 0 \sum x_i^2-\sum x_ix_0 xi2xix0
∑ x i 2 − ( ∑ x i ) 2 / n \sum x_i^2-(\sum x_i)^2/n xi2(xi)2/n
n ∑ x i 2 − ( ∑ x i ) 2 n\sum x_i^2-(\sum x_i)^2 nxi2(xi)2
(这个是比赛的时候拆的,最后答案乘了 n 2 n^2 n2

再看范围很小。
考虑直接暴力 DP。
直接设 f i , j , k f_{i,j,k} fi,j,k 为当前到 ( i , j ) (i,j) (i,j) 的位置, ∑ x i \sum x_i xi 的大小是 k k k 时,左边那项的最小值。
然后直接枚举从左边从上面来即可。

代码

#include<cstdio>
#include<cstring>
#include<iostream>

using namespace std;

int n, m, a[51][51];
int f[51][51][5001];
bool cn[51][51][5001];
int ans;

int main() {
//	freopen("path.in", "r", stdin);
//	freopen("path.out", "w", stdout);
	
	memset(f, 0x7f, sizeof(f));
	
	scanf("%d %d", &n, &m);
	for (int i = 1; i <= n; i++)
		for (int j = 1; j <= m; j++) {
			scanf("%d", &a[i][j]);
		}
	
	cn[1][1][a[1][1]] = 1;
	f[1][1][a[1][1]] = a[1][1] * a[1][1];
	for (int i = 1; i <= n; i++)
		for (int j = 1; j <= m; j++) {
			if (i == 1 && j == 1) continue;
			for (int k = a[i][j]; k <= 50 * (n + m - 1); k++) {
				if (cn[i - 1][j][k - a[i][j]]) {
					cn[i][j][k] = 1;
					f[i][j][k] = min(f[i][j][k], a[i][j] * a[i][j] + f[i - 1][j][k - a[i][j]]);
				}
				if (cn[i][j - 1][k - a[i][j]]) {
					cn[i][j][k] = 1;
					f[i][j][k] = min(f[i][j][k], a[i][j] * a[i][j] + f[i][j - 1][k - a[i][j]]);
				}
			}
		}
	
	ans = 2e9;
	for (int k = 0; k <= 50 * (n + m - 1); k++)
		if (cn[n][m][k])
			ans = min(ans, (n + m - 1) * f[n][m][k] - k * k);
	printf("%d", ans);
	
	return 0;
}
  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值