LDUOJ - 1.25训练赛 -D. 成为王的痛苦 (前缀最大值优化dp)

图解

@光巨
在这里插入图片描述

Description
“拔出石中剑,你便是王”。
“拔剑之前,你最好先想一想。因为一旦拔起剑,你将不再是人类,你会被所有人类憎恶,你将最终迎来悲剧的死亡。”魔术师梅林如是说。
然而名为Arturia Pendragone的少女还是拔起了剑,成为了英格兰之王。
一天,王发现她拔出的石中剑上有N个凹槽,经过多年征战,她一共收集了M块宝石,并且N≥M。将每块宝石放到每一个凹槽中都会使石中剑具有一定的美丽值(可能为负数)。
若1≤i<j≤M,则编号为i的宝石所在的凹槽的编号一定要小于编号为j的宝石所在的凹槽的编号。
由于王也是女孩子,所以她希望这个美丽值最大。
当然,每个凹槽只能放入一 块宝石,每块宝石也只能放入一个凹槽。
每块宝石都必须被使用到。

Input
第一行,两个整数N,M;
接下来M行,每行N个整数,表示这一块宝石放入这一个凹槽的美丽值。

Output
一行,表示美丽值的最大可能值。

Input Copy
3 2
-10 10 10
0 30 10
Output
20
Hint
【数据范围】

对于10%的数据,M=1
另外20%的数据,1≤M≤5 M≤N≤20
对于100%的数据,1≤M≤N≤1500
每个宝石的美丽值保证大于−105,小于105

题目大意:

m行n列的矩阵,从一行开始每一行可以选择一个位置的权值
但是如果第一行选择的第j列的位置
那么再往下选的时候只能选大于j 列的列

题目思路:

dp[i][j] 代表第i个宝石 放在第j个坑的最大值
朴素方程	dp[i][j] = dp[i-1][k] + val[i][j];  k<j

此时发现 需要三层循环
但是时间复杂度并不允许
可以用前缀的最大值优化掉 dp[i-1][k] 这一项

新的方程为
dp[i][j] = max(dp[i][j],pre[j-1]+val[i][j]);
pre[j-1] 是上一行中的宝石放在了j-1列之前的列的最大值
当然pre数组也可以开二维(类似背包)

Code:

int  n,m,val[2212][2221],s[2121][2221],num[2121],dp[2121][2121],pre[2211];
int main() {
    
    
	n=read(),m=read();
	rep(i,0,n) rep(j,0,m) dp[i][j] = -inf;
	rep(i,1,m) rep(j,1,n) val[i][j] = read();
	
	for(int i=1 ; i<=m ; i++) {
    
    
		for(int j=i ; j<=n ; j++) 	dp[i][j] = max(dp[i][j],pre[j-1]+val[i][j]);
		for(int j=i ; j<=n ; j++) {
    
    
			num[j] =  dp[i][j];
			if(j==i) pre[j] = num[j];
			else pre[j] = max(pre[j-1],num[j]);
		}
	}
	int ans = -inf;
	for(int i=m ; i<=n ; i++) ans = max(ans,dp[m][i]);
	out(ans);
	return 0;
}

猜你喜欢

转载自blog.csdn.net/wmy0536/article/details/113203769