Live2D

Solution -「CF 1372E」Omkar and Last Floor

Description

  Link.

  给定一个 n×m 的矩阵,每行被划分为若干段,你可以钦定每段中恰好一个位置为 1,其余位置为 0。设 ci 为第 i1 的个数,最大化 i=1mci2

  n,m100

Solution

  区间 DP,不过状态设计比较巧妙:令 f(l,r) 表示确定[l,r] 区间内的所有段的最大和。记 cl,r,k 表示在区间 [l,r] 内,包含了第 k 列的段的个数,转移:

f(l,r)=maxk[l,r]{f(l,k1)+f(k+1,r)+cl,r,k2}

  复杂度 O(n4)(求转移时在线求 cl,r,k)。

Code

/* Clearink */

#include <cstdio>

const int MAXN = 100;
int n, m, f[MAXN + 5][MAXN + 5], L[MAXN + 5][MAXN + 5], R[MAXN + 5][MAXN + 5];

inline void chkmax ( int& a, const int b ) { a < b ? a = b : 0; }

int main () {
	scanf ( "%d %d", &n, &m );
	for ( int i = 1, k; i <= n; ++ i ) {
		scanf ( "%d", &k );
		for ( int j = 1, l = 1, r; j <= k; ++ j, l = r + 1 ) {
			scanf ( "%*d %d", &r );
			for ( int h = l; h <= r; ++ h ) L[h][i] = l, R[h][i] = r;
		}
	}
	for ( int len = 1; len <= m; ++ len ) {
		for ( int l = 1, r; ( r = l + len - 1 ) <= m; ++ l ) {
			int& cur = f[l][r] = -1;
			for ( int k = l; k <= r; ++ k ) {
				int c = 0;
				for ( int h = 1; h <= n; ++ h ) c += l <= L[k][h] && R[k][h] <= r;
				chkmax ( cur, f[l][k - 1] + f[k + 1][r] + c * c );
			}
		}
	}
	printf ( "%d\n", f[1][m] );
	return 0;
}
posted @   Rainybunny  阅读(88)  评论(0编辑  收藏  举报
编辑推荐:
· AI与.NET技术实操系列:基于图像分类模型对图像进行分类
· go语言实现终端里的倒计时
· 如何编写易于单元测试的代码
· 10年+ .NET Coder 心语,封装的思维:从隐藏、稳定开始理解其本质意义
· .NET Core 中如何实现缓存的预热?
阅读排行:
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· ollama系列01:轻松3步本地部署deepseek,普通电脑可用
· 25岁的心里话
· 按钮权限的设计及实现
点击右上角即可分享
微信分享提示