线性DP入门2

学dp已经第十五天了,感觉自己没有多少进步。反而一天比一天焦躁。
别人最快的已经做了22个题了,而我才做了8个题。现在是一点也狂妄不起来了。。。。
不过还是稍微有点感觉了,也挺值得开心的,虽然远远不够。
总之学东西不要急,要沉下心来搞清楚原理。学DP时,我觉得把每一步写出来,或者用画图的形式画出来(推荐画图,思路比较清晰,如果实在不知道过程怎么来的就把每一步写下来),虽然可能耗费很多时间,但当你一步步看下来就会逐渐搞清楚DP的过程。

根据这周的课,我还是对这个动态规划有了一写更明确的学习方向。100道不同的dp问题。饭要一口一口吃。针对本周的题得出的想法如下;
列一
此题是对以前的题得复习如下
求一个M*N的矩阵的最大子矩阵和。
比如在如下这个矩阵中:
0 -2 -7 0
9 2 -6 2
-4 1 -4 1
-1 8 0 -2
拥有最大和的子矩阵为:
9 2
-4 1
-1 8
其和为15。
思路:

首先,这个子矩阵可以是任意大小的,而且起始点也可以在任何地方,所以,要把最大子矩阵找出来
假定原始矩阵的行数为M,那么对于子矩阵,它的行数可以是1到M的任何一个数,而且,对于一个K行(K < M)的子矩阵,它的第一行可以是原始矩阵的第1行到 M - K + 1 的任意一行。
这也就是说可以把这个理解成子问题
而且在求最大子矩阵的 时候我们可以通过以前对最大字段和问题进行类比
具体假设如下

假设这个最大子矩阵的维数是一维,要找出最大子矩阵, 原理与求“最大子段和问题” 是一样的。最大子段和问题的递推公式是 b[j]=max{b[j-1]+a[j], a[j]},b[j] 指的是从0开始到j的最大子段和。
但是这是一个二维的要找出最大子矩阵,我们要从左到右不断的遍历才能找出在这种情况下的最大子矩阵。如果我们把这两行上下相加,情况就和求“最大子段和问题” 又是一样的了
`。为了找出在原始矩阵里的最大子矩阵,我们要遍历所有的子矩阵的可能情况,也就是说,我们要考虑这个子矩阵有可能只有1行,2行,。。。到n行。而在每一种情况下,我们都要把它所对应的矩阵部分上下相加才求最大子矩阵(局部)。

#include<iostream>
#include<cstring>
#include<algorithm>
using namespace std;
int main()
{
	int N[505][505];
	memset(N,0,sizeof(N));
	int n,m;
	cin>>m>>n;
	for(int i=1;i<=n;i++)
	{
		for(int j=1;j<=m;j++)
		{
			cin>>N[i][j];
			N[i][j]+=N[i-1][j];
		}
	}
	int sum,ans=0;
	for(int i=1;i<=n;i++)
	{
		for(int j=i;j<=n;j++)
		{
			sum=0;
			for(int k=1;k<=m;k++)
			{
				sum+=N[j][k]-N[i-1][k];
				if(sum<0)
					sum=0;
				ans=max(sum,ans);
			}
		}
	}
	cout<<ans<<endl;
	return 0;

}`

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

聆听我的召唤,菜鸟进化

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值