问题描述:个人做笔记使用,如有侵权联系删除,谢谢!
最大子列和问题是最大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段?
终于看了代码自己草稿纸上演算网上的代码画图懂了
0 | 1 | 2 | 3 | 4 | 5 | 6 | |||
---|---|---|---|---|---|---|---|---|---|
0 | -1 | -4 | -2 | 3 | 2 | 3 | |||
a[0,j] | 0 | 0 | 0 | 0 | 0 | 0 | 0 | ||
a[1,j] | 0 | -1 | 4 | 2 | 5 | 3 | 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);
}
}