题解 CF1372E Omkar and Last Floor

题目链接

首先,因为((a+b)^2geq a^2+b^2),所以我们总是希望让(1)更加“集中”。当然,这只是一个抽象的原则,具体决策还得靠DP。

考虑区间DP。

(dp[i][j])表示对于([idots j])这些列,只考虑被([i,j])完全包含的区间,能达到的最大价值。

转移时,我们枚举一个(kin[i,j]),表示把(1)尽可能集中到第(k)列。设所有跨过(k)且被([i,j])完全包含的区间数量为( ext{cnt}(k))(这里的“区间”,其实就是指每一行的第(k)列所在的区间)。则:

[dp[i][j]=max_{kin[i,j]}{dp[i][k-1]+dp[k+1][k]+ ext{cnt}(k)^2} ]

答案就是(dp[1][m])

时间复杂度(O(nm^3))

参考代码:

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

#define pb push_back
#define mk make_pair
#define lob lower_bound
#define upb upper_bound
#define fi first
#define se second
#define SZ(x) ((int)(x).size())

typedef unsigned int uint;
typedef long long ll;
typedef unsigned long long ull;
typedef pair<int,int> pii;

template<typename T>inline void ckmax(T& x,T y){x=(y>x?y:x);}
template<typename T>inline void ckmin(T& x,T y){x=(y<x?y:x);}

const int MAXN=100;
const int INF=1e9;
int n,m,st[MAXN+5][MAXN+5],ed[MAXN+5][MAXN+5];
vector<pii> seg[MAXN+5];

int dp[MAXN+5][MAXN+5];
int main() {
	cin>>n>>m;
	for(int i=1;i<=n;++i){
		int sz;cin>>sz;
		seg[i].resize(sz);
		for(int j=0;j<sz;++j){
			cin>>seg[i][j].fi>>seg[i][j].se;
			for(int k=seg[i][j].fi;k<=seg[i][j].se;++k){
				st[i][k]=seg[i][j].fi;
				ed[i][k]=seg[i][j].se;
			}
		}
	}
	for(int i=1;i<=m;++i){
		for(int j=1;j<=m;++j){
			dp[i][j]=-INF;
			if(i==j){
				int cnt=0;
				for(int k=1;k<=n;++k)
					cnt+=(st[k][i] == ed[k][i]);
				dp[i][j]=cnt*cnt;
			}
		}
	}
	for(int len=2;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 l=1;l<=n;++l)
					cnt+=(st[l][k]>=i && ed[l][k]<=j);
				ckmax(dp[i][j],(k==i?0:dp[i][k-1])+(k==j?0:dp[k+1][j])+cnt*cnt);
			}
		}
	}
	cout<<dp[1][m]<<endl;
	return 0;
}
原文地址:https://www.cnblogs.com/dysyn1314/p/13321867.html