算法分析与设计实验——动态规划算法

实验目的和要求

  1. 深刻掌握动态规划法的设计思想并能熟练运用;
  2. 掌握动态规划法设计算法的三个阶段:分段:将原问题分解为若干个相互重叠的子问题;分析:分析问题是否满足最优性原理,找出动态规划函数的递推式;求解:利用递推式自底向上计算,实现动态规划过程。
  3. 用动态规划法设计最大子段和问题和0-1背包问题的算法;
  4. 通过随机数函数给出测试数据进行测试,并与蛮力法进行对比。

实验内容

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学时,必做实验

数据结构与算法

  1. 最大子段和问题——动态规划

a[]数组来存储原序列内容

b[]数组存储字段

max用来记录最大字段和

n来定义个数

  1. 0-1背包问题——动态规划

W[]数组记录物品重量

V[]数组记录物品价值

V[][]二维数组记录迭代结果

X[]数组记录背包物品

  1. 青蛙跳台阶问题——动态规划

N记录台阶数

A记录模1000000007

  1. 股票的最大利润——动态规划

Length记录需要存储的个数

Number[]数组记录存储的价格

核心源代码

  1. 最大子段和问题:

#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;

}

  1. 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;

}

  1. 青蛙跳台阶问题

#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);

}

  1. 股票的最大利润

#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)股票的最大利润

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值