codeforces 1372E Omkar and Last Floor(区间DP)

原题链接
题意:有若干行,每行分为若干段,每段可以选定一个位置放入一个1,求放完所有1以后每列1个数的平方数之和的最大值
题解:题目后效性很强,考虑DP,设范围 i i i ~ j j j的最大值为 D P [ i ] [ j ] DP[i][j] DP[i][j],考虑合并两个区间,感觉没有思路,于是取出一条,再与两边区间合并,显然根据贪心思路,这一条尽可能全选,但会存在后效性,即两边区间该段已有选择位置置1。所以添加一个限制,令 D P [ i ] [ j ] DP[i][j] DP[i][j]中能置1的段都要包括在 i i i ~ j j j内,这样便不会和新增的一条冲突,如此区间DP的转移方程便可得出 D P [ i ] [ j ] = m a x ( D P [ i ] [ j ] , D P [ i ] [ k − 1 ] + D P [ k + 1 ] [ j ] + ( ∑ x = 1 x < = n ( 第 x 行 k 列 所 在 的 段 在 i 到 j 中 ) ) DP[i][j]=max(DP[i][j],DP[i][k-1]+DP[k+1][j]+(\sum_{x=1}^{x<=n}(第x行k列所在的段在i到j中)) DP[i][j]=max(DP[i][j],DP[i][k1]+DP[k+1][j]+(x=1x<=n(xkij))
其中 x x x k k k列所在的段要预处理

代码如下

#include<bits/stdc++.h> 
using namespace std;

int n,m;
int dp[111][111]; 
int num;
int l[110][110],r[110][110];


int main()
{
	scanf("%d%d",&n,&m);
	for(int i=1;i<=n;i++)
	{
		int tmp,ll,rr;
		scanf("%d",&tmp);
		for(int j=1;j<=tmp;j++)
		{
			scanf("%d%d",&ll,&rr);
			for(int j=ll;j<=rr;j++)
			{
				l[i][j]=ll;
				r[i][j]=rr;
			}
		} 
	}
	for(int len=1;len<=m;len++)
	{
		for(int i=1;i+len-1<=m;i++)
		{
			int j=i+len-1;
			for(int k=i;k<=j;k++)
			{
				int cnt=0;
				for(int x=1;x<=n;x++) if(i<=l[x][k]&&r[x][k]<=j) cnt++;
				dp[i][j]=max(dp[i][k-1]+dp[k+1][j]+cnt*cnt,dp[i][j]);
			}
		} 
	}
	printf("%d\n",dp[1][m]);
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值