最大子列和最大M字段和与

问题描述:个人做笔记使用,如有侵权联系删除,谢谢!

 

 

 

最大子列和问题是最大M字段和的特殊情况

动态规划一般我们要推导出递推公式

我碰到的难点主要是:怎么确定就分了m段,m段问题怎么解决?最大之列和问题不用考虑m段,

最大之列和的递推公式:

可以用递归,用备忘录,自顶向下

//最大连续之列和问题  备忘录 
#include<iostream>
#include<algorithm>
#include<cstring>
using namespace std;
#define max(x,y) x>y?x:y
const int M=1000; 
int a[1000];
int note[1000];
int n;
int gcd(int i){
	if(note[i]>0) return note[i];
	if(i==0) {
		note[0]=a[0];
		return a[0];
	}
	else  note[i]= max(gcd(i-1)+a[i],a[i]);
	cout<<note[i]<<" ";
    return note[i];
}
int main()
{
//	int n;
while(cin>>n){
    memset(note,0,sizeof(note));
	for(int i=0;i<n;i++) cin>>a[i];
	gcd(n-1);
	sort(note,note+n);
	cout<<note[n-1]<<endl;
} }

比较直白简单,这个问题怎么确定M段?

终于看了代码自己草稿纸上演算网上的代码画图懂了

递推分析
 0123456  
 0-1-4-223  
a[0,j]0000000  
a[1,j]0-14253  1--5
a[2,j]0     8 1--6

 

画表是前提,我画表后才懂了网上的代码,自己独立实践成功

其实递推就是确定j段内最大的  p[i][j-1],  再加入a[j]

递推分析:

公式其实要不要无所谓,我觉得最受益匪浅的是我看到了动态规划的分层,

分段m段就是留最后的M个元素做准备,1-----5       2-----6  a[5]  a[6];

数组p[i][j]来记录 i表示i段 ,j表示前j个元素,

初始化数组

p[i][j]全为0

//最大M子数列 自我实现 
#include<iostream>
#include<cstring>
using namespace std;
const int M=100;
int a[M];
int p[M][M];
int gcd(int m,int n){//m表示段数,n表示元素个数 
	for(int i=1;i<=m;i++){
		for(int j=i;j<=n-m+i;j++){
			p[i][j]=p[i][j-1]+a[j];
			for(int k=i-1;k<=j-1;k++) {  
				if(p[i][j]<p[i-1][k]+a[j])  p[i][j]=p[i-1][k]+a[j];
				cout<<p[i][j]<<" ";
			}
		}
		cout<<"dhkahdkh"<<endl;
	} 
		int sum=0;
		for(int i=m;i<=n;i++)
		{
			if(p[m][i]>sum) sum=p[m][i];
		}
  return sum;
}
int main(){
	int m,n;
	memset(a,0,sizeof(a));
	memset(p,0,sizeof(p));
	while(cin>>m>>n){
		for(int i=1;i<=n;i++)
		cin>>a[i];
		cout<<"hello"<<endl;
	cout<<gcd(m,n);
	} 

} 

 

 

 

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值