1. 最大子段和
一键三连1
给定由n个整数(可能有负整数)组成的序列(a1,a2,…,an),最大子段和问题要求该序列形如 的最大值(1<=i<=j<=n),当序列中所有整数均为负整数时,其最大子段和为0。
最大子段和作为动态规划算法中的经典例题,是值得我们去学习考究的
- 用动态规划法求解。
算法思想可以参考:
我的实现代码:
#include<iostream>
using namespace std;
/**
* 状态dp数组dp[i]表示前i个元素中 取1<=j<=i,a[i]加到a[j]的最大值
*/
int main()
{
int n,i,max;
cout<<"enter n:";
cin>>n;
int *a=new int[n+1];
int *dp=new int[n+1];
cout<<"enter the number:";
for(i=1;i<=n;i++)
cin>>a[i];
dp[0]=0;
max=dp[0];
for(i=1;i<=n;i++)
{
//状态转移方程
if(dp[i-1]>=0) dp[i]=dp[i-1]+a[i];
else dp[i]=a[i];
if(dp[i]>max) max=dp[i];
}
cout<<"MAX:"<<max<<endl;
system("pause");
return 0;
}
运行结果:
2、最大k乘积
算法思想参考博客2
这位大佬讲的是我觉得最通俗易懂的,真不错,看了那么多篇相对垃圾博客
代码参考博客3
最大k乘积问题。
问题描述:设X是一个n位十进制整数,如果将X划分为K段,则可得到K个整数,这K个整数的乘积称为X的一个K乘积。请设计算法并编程实现,对于给定的X 和K,求出X的最大K乘积。
输入:X,K,n
输出:X的最大K乘积。
分析可得其满足动态规划条件
- m数组表示状态m[i][j]表示将前i个数划分为j份乘积最大值
- 同时状态转移方程:
M[i][j]=Max{ m[x][j-1]*number[x+1][i]};
这里我们使用cal()自定义函数来计算x+1至i那段的数据大小
实现代码:
#include<iostream>
using namespace std;
int cal(char* num,int i,int j){
int value=0;
while(j>=i){
value=value*10+(num[i]-'0');
i++;
}
return value;
}
int main(){
int n,k; //n代表整数有n位,k指分成多少段
cin>>n>>k;
getchar();
char num[n+1]; //接收单个字符
int m[n+1][n+1]; //m[i][j] 前i个数字,分成j段
int max,value;
for(int i=1;i<n+1;i++){
cin>>num[i];
}
//数组打底
m[1][1]=num[1]-'0';
for(int i=2;i<n+1;i++)
m[i][1]=m[i-1][1]*10+(num[i]-'0'); //前i个数字,分成一段
for(int i=2;i<=k;i++){ //分成多少段
max=-1;
for(int j=i;j<n+1;j++){ //j从开始遍历到最后一个数,因为i<j时(前3个数,分成4段),无意义,所以直接令j=i
for(int d=1;d<=j-1;d++){
value=m[d][i-1]*cal(num,d+1,j);
if(value>max)
max=value;
}
m[j][i]=max;
}
}
cout<<"The max:"<<m[n][k]<<endl;
system("pause");
return 0;
}
运行结果: