动态规划常见题目解析:
分别为:
1.最长公共子序列
2.最大字段和
3.0-1背包问题
下面逐一描述:
1.最长公共子序列
题目描述:
例如对于X={A,B,C,B,D,A,B},Y={B,D,C,A,B,A},则序列{B,C,B,A}就是X和Y的最长公共子序列。
解法:
按照该思路的解法:
#include <iostream>
using namespace std;
//动态规划算法-最长公共子序列
//m,n代表数组x和y的长度,c[i][j]表示Xi和Yj的最长公共子序列的长度,
//b[i][j]记录c[i][j]是由哪一种子问题的解得到的
void LCSLength(int m,int n,char x[],char y[],int c[][7],int b[][7])
{
int i,j;
for (i=1;i<=m;i++) c[i][0]=0;
for (i=1;i<=n;i++) c[0][i]=0;
for (i=1;i<=m;i++)
for (j=1;j<=n;j++)
{
if (x[i]==y[j])//第一种解的情况
{
c[i][j]=c[i-1][j-1]+1;
b[i][j]=1;
}else if (c[i-1][j]>=c[i][j-1])//第二种解的情况
{
c[i][j]=c[i-1][j];
b[i][j]=2;
}else//第三种解的情况
{
c[i][j]=c[i][j-1];
b[i][j]=3;
}
}
}
//构造最长子序列
void LCS(int i,int j,char x[],int b[][7])
{
if (i==0 || j==0) return;
if (b[i][j]==1)
{
LCS(i-1,j-1,x,b);
cout<<x[i]<<'\t';
}else if (b[i][j]==2)
LCS(i-1,j,x,b);
else
LCS(i,j-1,x,b);
}
int main()
{
char x[]={'Z','A','B','C','B','D','A','B'};//长度为8
char y[]={'Z','B','D','C','A','B','A'};//长度为7
int c[8][7];
int b[8][7];
LCSLength(7,6,x,y,c,b);
LCS(7,6,x,b);
cout<<endl;
return 0;
}
2.最大字段和
问题描述:给定n个整数(可能有负整数)组成的序列a1,a2,...,an,求ai...aj的最大值,0<=i,j<n,例如当数组为{-2,11,-4,13,-5,-2}时,最大字段和为11+(-4)+13=20.
解法描述:
#include <iostream>
using namespace std;
//解法一:时间复杂度为O(n^2)
//n表示数组的长度,besti和bestj分别表示大子段的起止位置
int MaxSum1(int n,int a[],int &besti,int &bestj)
{
int sum=0;
for (int i=0;i<n;i++)
{
int tempsum=0;
for (int j=i;j<n;j++)
{
tempsum+=a[j];
if (tempsum>sum)
{
sum=tempsum;
besti=i;
bestj=j;
}
}
}
return sum;
}
//解法二:时间复杂度为O(n)
int MaxSum2(int n,int a[],int &besti,int &bestj)
{
int sum=0,b=0;
for (int i=0;i<n;i++)
{
if (b>0)
{
b+=a[i];
if (a[i]>=0)//最后一个数字肯定是非负数
bestj=i;
}
else
{
b=a[i];
besti=i;//第一个数字肯定也是非负数,但无需判断
}
if (b>sum)
sum=b;
}
return sum;
}
int main()
{
int arr[6]={-2,11,-4,13,-5,-2};
int besti,bestj;
//cout<<MaxSum1(6,arr,besti,bestj)<<endl;
cout<<MaxSum2(6,arr,besti,bestj)<<endl;
cout<<besti<<"---"<<bestj<<endl<<"最大字段和序列如下:"<<endl;
for (int i=besti;i<=bestj;i++)
{
cout<<arr[i]<<endl;
}
return 0;
}
3.0-1背包问题
问题描述:给定n种物品和一背包,物品i的重量是w[i],其价值为v[i]背包的容量为c,问应如何选择放入背包的物品是背包的总价值最大?
说明:物品只有两种选择:放入背包和不放入背包。
解法1描述:(效率较低,有条件限制:背包重量必须为正整数)
#include <iostream>
#define min(x,y)((x)>(y)?y:x)
#define max(x,y)((x)<(y)?y:x)
using namespace std;
//动态规划-0-1背包问题
//n表示有n个物品,v[n]存储的是物品价值,w[n]存储的是物品重量
//m[i][j]表示背包容量为j,可选物品是i,i+1,...,n时背包问题的最优解
//m[i][j]的递归式如下:
//m[i][j] = 1.max{m[i+1,j],m[i+1,j-w[i]]+v[i]} j>=w[i];
// 2.m[i+1,j] 0<=j<w[i]
//m[n][j] = 1.v[n] j>=w[n];
// 2.0 0<=j<w[n]
//递归式解释:i=n的情况不需要解释,很容易理解;对于i的情况,如果0<=j<w[i],则i元素肯定不放在
//背包中,所以和m[i+1,j]是相等的,如果j>=w[i],也就是说i元素有放入背包的可能,如果不放入背包,和
//0<=j<w[i]的情况是一样的,即m[i+1,j],如果放入背包,就是先要求出背包元素为i+1至n,背包重量为j-w[i]的
//最优解即m[i+1,j-w[i]]然后再加上v[i],最后比较这这两个值的最大值。
//说明:该算法结束之后,容易看出m[1][c]即为背包问题的最优解
//v,w中的元素是从0->n-1;m中的元素是从1->n。
void Knapsack(int v[],int w[],int c,int n,int m[][11])
{
int i,j;
//首先计算当i=n-1的时候背包的最优解
int jMax=min(w[n-1],c);
//下面的两个语句考虑到了最小值为w[n-1]或者是c的情况
for (j=0;j<jMax;j++)//当j<jMax时,求相应的最优解
m[n][j]=0;
for (j=w[n-1];j<=c;j++)//当w[n-1]<=j<=c的时候,求相应的最优解,如果c<w[n-1],不执行下面的语句,上面的语句已经求出最优解
m[n][j]=v[n-1];
//然后计算0<i<n-1时的最优解
for (i=n-2;i>0;i--)
{
jMax=min(w[i],c);
for (j=0;j<jMax;j++)
m[i+1][j]=m[i+2][j];
for (j=w[i];j<=c;j++)
m[i+1][j]=max(m[i+2][j],m[i+2][j-w[i]]+v[i]);
}
//最后计算i=0时的最优解
m[1][c]=m[2][c];
if (c>=w[0])
m[1][c]=max(m[2][c],m[2][c-w[0]]+v[0]);
}
//将最优解构造出来,放到数组x[]中
void Traceback(int m[][11],int w[],int c,int n,int x[])
{
for (int i=1;i<n;i++)
{
if (m[i][c]==m[i+1][c])//说明i不在背包中
x[i]=0;
else//i在背包中
{
x[i]=1;
c-=w[i-1];
}
}
x[n]=(m[n][c])>0?1:0;
}
int main()
{
int w[]={2,2,6,5,4};
int v[]={6,3,5,4,6};
int c=10;
int x[6];
int m[6][11];
Knapsack(v,w,c,5,m);
Traceback(m,w,c,5,x);
cout<<"最优解是:"<<endl;
for (int i=1;i<=5;i++)
cout<<i<<":"<<x[i]<<endl;
return 0;
}
解法1描述:(效率提升)
- 大小: 410.2 KB
分享到:
相关推荐
代码 随机动态规划的实例的matlab代码代码 随机动态规划的实例的matlab代码代码 随机动态规划的实例的matlab代码代码 随机动态规划的实例的matlab代码代码 随机动态规划的实例的matlab代码代码 随机动态规划的实例的...
动态规划是求解最优化问题的一种方法;动态规划虽然空间复杂度一般较大,但时间效率可观。但是,动态规划在求解中也会存在一些不必要、或者重复求解的子问题,这时就需要进行进一步优化。 在NOI及省选赛场上,一般...
【基于LINGO的优化问题动态规划法求解】 在运筹优化领域,LINGO是一款强大的数学建模软件,尤其适用于解决各种线性、非线性以及动态规划问题。不同于传统方法,LINGO甚至可以在没有明确目标函数的情况下解决动态...
本实验报告主要探讨了使用动态规划算法解决计算二项式系数的问题。实验者刘春云,专业为软件工程,通过这个实验学习并应用了动态规划这一核心的计算机科学概念。实验指导教师为赵晓平,实验时间为2012年2月21日。 *...
动态规划算法经典题目分析 动态规划是一种非常经典的算法思想,解决的问题领域非常广泛。动态规划的基本思想是将一个复杂的问题分解成多个小问题,通过解决这些小问题来解决整个问题。今天,我们将要探讨动态规划的...
动态规划是信息学竞赛中的常见算法,本文的主要内容就是分析 它的特点。 文章的第一部分首先探究了动态规划的本质,因为动态规划的特 点是由它的本质所决定的。第二部分从动态规划的设计和实现这两个 角度分析了动态...
动态规划是一种重要的算法思想,广泛应用于计算机科学,特别是在解决最优化问题时,如图论、组合优化、机器学习和自然语言处理等领域。在ACM(国际大学生程序设计竞赛)中,动态规划也是常考的题型,因为它能够帮助...
会议安排(贪心算法和动态规划) 会议安排问题是计算机科学中的一种经典问题,目的是在一系列活动中选择尽可能多的活动,使得每个活动的结束时间不早于下一个活动的开始时间。这个问题可以使用贪心算法和动态规划两...
贪心算法、分治算法和动态规划的区别 贪心算法、分治算法和动态规划是三种常用的算法设计策略,每种算法都有其特点和应用场景。下面我们将对这三种算法进行详细的比较和分析。 分治算法 分治算法是一种将原问题...
贪心算法、动态规划和分治法的区别 贪心算法是局部最优解的算法,它通过从上往下,从顶部一步一步最优,得到最后的结果。贪心算法顾名思义,就是做出在当前看来是最好的结果,它不从整体上加以考虑,也就是局部最优...
动态规划是一种解决问题的有效方法,尤其在处理具有重叠子问题和最优子结构的复杂问题时。旅行商问题(Traveling Salesman Problem, TSP)是一个经典的组合优化问题,它的目标是找到一个城市的最短可能路线,使得...
动态规划(Dynamic Programming,简称DP)是一种用于解决最优化问题的算法思想,它通过将大问题分解为相互重叠的子问题,并存储子问题的解,以避免重复计算,从而达到高效求解的目的。DP的核心在于它能够识别并利用...
从给定的文件标题“算法动态规划总结(拓展篇)”和描述“算法动态规划拓展总结,内含详细解说和代码”中,我们可以提炼出一系列关于动态规划算法的知识点,这些知识点涵盖了动态规划的多种应用及其优化技术。...
"动态规划C语言矩阵连乘" 动态规划是一种非常重要的算法思想,它可以解决很多 Optimization 问题。在这个资源中,我们将学习如何使用动态规划来解决矩阵连乘问题。 动态规划的基本思想是将待解决的问题分解成若干...
标题中的“dynprogs_MATLAB动态规划函数及测试程序_多阶段决策_多阶段规划_together1rz_”表明这是一个关于使用MATLAB实现动态规划算法的资源包,主要用于解决涉及多阶段决策和规划的问题。动态规划是一种在数学、...
动态规划增量动态规划水库优化调度程序代码 动态规划是一种常用的优化算法,它可以解决很多复杂的优化问题。增量动态规划是动态规划的一种变体,它可以更好地解决一些特殊的优化问题。在水库优化调度中,动态规划和...
动态规划(Dynamic Programming,简称DP)是解决复杂问题的有效算法设计方法,尤其在计算机科学和IT领域中占有重要地位。它通过将一个大问题分解为若干个子问题,并利用子问题的解来构建原问题的解,从而避免了重复...
本篇文章将深入探讨如何运用LINGO来解决动态规划问题,通过具体的案例分析,我们将了解LINGO在动态规划中的应用方法和步骤。 ### 动态规划与LINGO 动态规划是一种用于解决多阶段决策过程中的最优化问题的方法,其...