动态规划常见题目解析:
分别为:
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代码代码 随机动态规划的实例的...
动态规划是信息学竞赛中的常见算法,本文的主要内容就是分析 它的特点。 文章的第一部分首先探究了动态规划的本质,因为动态规划的特 点是由它的本质所决定的。第二部分从动态规划的设计和实现这两个 角度分析了动态...
在计算机算法设计方法中,动态规划技术是比较基本,但又比较抽象,难于理解的一种。它建立在最优原则的基础上,动态规划 ( dynamic programming )算法是解决多阶段决策过程最优化问题的一种常用方法,难度比较大,...
(1) 动态规划算法设计思想。 (2) 金罐游戏问题的动态规划解法。 算法设计与分析-4动态规划金罐游戏.pptx 蛮力法(简单重复递归)和动态规划解决金罐问题 状态数组 子问题 状态方程 蛮力法(时间复杂度O(2n))和...
动态规划是解决多阶段决策最优化问题的一种思想方法。所谓“动态”,指的是在问题的多阶段决策中,按某一顺序,根据每一步所选决策的不同,将随即引起状态的转移,最终在变化的状态中产生一个决策序列。动态规划就是...
矩阵相乘问题的动态规划,动态规划是解决多阶段决策过程最优化问题的一种方法,其思想是将求解的问题一层一层地分解成一级一级的子问题,子问题的求解由繁到简逐步缩小,直到可以直接解出子问题为止。下面用动态规划...
会议安排(贪心算法和动态规划) 贪心算法和动态规划.pdf
应用动态规划算法思想求解矩阵连乘的顺序问题。 【实验性质】 验证性实验(学时数:2H) 【实验要求】 应用动态规划算法的最优子结构性质和子问题重叠性质求解此问题。分析动态规划算法的基本思想,应用动态规划策略...
学习动态规划必备~ 动态规划~动态规划~动态规划~动态规划~动态规划~动态规划~动态规划~动态规划~动态规划~动态规划~动态规划~动态规划~动态规划~动态规划~
动态规划是求解最优化问题的一种方法;动态规划虽然空间复杂度一般较大,但时间效率可观。但是,动态规划在求解中也会存在一些不必要、或者重复求解的子问题,这时就需要进行进一步优化。 在NOI及省选赛场上,一般...
几道动态规划的经典算法 非常经典 值得分享
java 最短路径 问题 动态规划java 最短路径 问题 动态规划
最大子段和问题,可参考《算法设计与分析》讲义中关于用动态规划策略求解最大子段和问题的思想设计动态规划算法。本算法用户需要输入元素个数n,及n个整数。程序应该给出良好的用户界面,输出最大子段相关信息,包括...
这是一份简单的动态规划实验报告,独立完成的,参考了一些资料
详细阐述动态规划的应用范围及方法 动态规划经典教程 引言:本人在做过一些题目后对DP有些感想,就写了这个总结: 第一节 动态规划基本概念 一,动态规划三要素:阶段,状态,决策。 他们的概念到处都是,我就不多说...
动态规划是解决多阶段决策问题最优化的一种数学方法,大约产生于50年代,1951年美国数学家数学家贝尔曼(R.Bellman)等人根据多阶段决策问题的特点,把多阶段决策问题变换为一系列相互联系的单阶段问题,然后逐个加以...
动态规划混合动力汽车模式切换程序,附带工况。
经典算法问题-TSP商旅问题(Traveling Salesman Problem),它是数学领域中著名问题之一。...代码包含遗传算法和动态规划来求解这个问题,里面有完整源代码,并且有详细注释,还有两者的比较分析。
12个ACM动态规划经典题 习题+分析+程序 (转载)