实验目的和要求
- 深刻掌握动态规划法的设计思想并能熟练运用;
- 掌握动态规划法设计算法的三个阶段:分段:将原问题分解为若干个相互重叠的子问题;分析:分析问题是否满足最优性原理,找出动态规划函数的递推式;求解:利用递推式自底向上计算,实现动态规划过程。
- 用动态规划法设计最大子段和问题和0-1背包问题的算法;
- 通过随机数函数给出测试数据进行测试,并与蛮力法进行对比。
实验内容
1、最大子段和问题。给定由n个整数组成的序列(a1, a2, …, an),最大子段和问题要求该序列形如 的最大值(1≤i≤j≤n),当序列中所有整数均为负整数时,其最大子段和为0。例如,序列(-20, 11, -4, 13, -5, -2)的最大子段和为:
2、0-1背包问题。有n个物品,其重量分别是{w1, w2, …, wn},价值分别为{v1, v2, …, vn},背包的容量为C,求背包能够获得的最大价值。
实验环境
VS 或VC++
实验学时
2学时,必做实验
数据结构与算法
- 最大子段和问题——动态规划
a[]数组来存储原序列内容
b[]数组存储字段
max用来记录最大字段和
n来定义个数
- 0-1背包问题——动态规划
W[]数组记录物品重量
V[]数组记录物品价值
V[][]二维数组记录迭代结果
X[]数组记录背包物品
- 青蛙跳台阶问题——动态规划
N记录台阶数
A记录模1000000007
- 股票的最大利润——动态规划
Length记录需要存储的个数
Number[]数组记录存储的价格
核心源代码
- 最大子段和问题:
#include<iostream>
using namespace std;
#define N 100
int a[N];
int main(){
int i,n,b[N],max;
printf("请输入序列个数:");
while(scanf("%d",&n)&&n!=0){
printf("请输入序列内容:");
for(i=1;i<=n;i++)
scanf("%d",&a[i]);
b[1]=a[1];
for(i=2;i<=n;i++){
if(b[i-1]>0)
b[i]=b[i-1]+a[i];
else
b[i]=a[i];
}
max=b[1];
for(i=1;i<=n;i++)
if(max<b[i])
max=b[i];
printf("最大字段和为:%d\n",max);
}
return 0;
}
- 0-1背包问题
#include<iostream>
using namespace std;
#define C 20//背包容量为20
#define N 6 //物品个数为6
int V[N+1][C+1];
int X[N+1];
int max(int x,int y){
return x>=y?x:y;
}
int KnapScak(int n,int w[],int v[]){
for(int i=0;i<=n;i++)
V[i][0]=0;
for (int j=0;j<=C;j++)
V[0][j]=0;
for(int i=1;i<=n;i++)
for(int j=1;j<=C;j++)
if(j<w[i])
V[i][j]=V[i-1][j];
else
V[i][j]= max(V[i][j],V[i-1][j-w[i]]+v[i]);
for(int j=C,i=n;i>0;i--){
if(V[i][j]>V[i-1][j]){
X[i]=1;
j=j-w[i];
} else
X[i]=0;
}
return V[n][C];
}
int main(){
int w[]={0,5,3,2,10,4,2};
int v[]={0,12,8,15,22,12,8};
int a = KnapScak(N,w,v);
printf("背包最大价值为:%d",a);
return 0;
}
- 青蛙跳台阶问题
#include<iostream>
using namespace std;
int wayStep(){
int n,ways;
printf("请输入台阶数n:");
scanf("%d",&n);
if(n==0)
return 1;
if(n==1)
return 1;
if(n==2)
return 2;
long dp0=0;
long dp1=1;
long dp2=2;
long A=1000000007;
for(int i=3;i<=n;i++){
dp0=dp1;
dp1=dp2;
dp2=(dp0+dp1)%A;
}
return dp2;
}
int main(){
int a=wayStep();
printf("%d",a);
}
- 股票的最大利润
#include<iostream>
using namespace std;
int MaxDiff(int *number,int length){
if(number== NULL || length<2)
return 0;
int min=number[0];
int MaxDiff = number[1]-min;
int MidDiff ;
for(int i=2;i<=length;i++){
if(number[i-1]<min){
min=number[i-1];
}
MidDiff = number[i-1]-min;
if(MaxDiff<MidDiff){
MaxDiff=MidDiff;
}
}
return MaxDiff;
}
int main(){
int length;
printf("请输入需要存储的价格个数:");
scanf("%d",&length);
int number[length];
printf("请输入需要存储的价格:");
for(int i=0;i<length;i++){
scanf("%d",&number[i]);
}
int a= MaxDiff(number,length);
printf("%d",a);
}
实验结果
(1)最大子段和问题
(2)0-1背包问题
(3)青蛙跳台阶问题
(4)股票的最大利润