《算法设计与分析》复习(3)

三、动态规划

  • 理解动态规划算法的概念;

动态规划算法与分治法类似,其基本思想也是将待求解问题分解成若干个子问题
如果能够保存已解决的子问题的答案,而在需要时再找出已求得的答案,就可以避免大量重复计算,从而得到多项式时间算法。

  • 掌握动态规划算法的基本要素;

1)最优子结构性质
2)重复子问题性质

  • 掌握设计动态规划算法的步骤。

1) 找出最优解的性质,并刻划其结构特征;
2) 递归地定义最优值;
3) 以自底向上的方式计算出最优值;
4) 根据计算最优值时得到的信息,构造最优解



3.1 矩阵连乘问题

问题描述:将矩阵连乘积 A i A i + 1 . . . A j A_iA_{i+1}...A_j AiAi+1...Aj 简记为A[i:j] ,这里i≤j 。计算A[i:j]。

3.2 最长公共子序列

问题描述:给定2个序列X={ x 1 , x 2 , … , x m x_1,x_2,…,x_m x1,x2,,xm}和 Y={ y 1 , y 2 , … , y n y_1,y_2,…,y_n y1,y2,,yn},找出X和Y的最长公共子序列。

LCSLength()函数用于计算出最优值

void LCSLength(int m, int n, char *x, char *y, int **c, int **b){
    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;
            }
    }
}

LCS()函数用于输出最长公共子序列

void LCS(int i, int j, char *x, int**b){
    if(i == 0 || j == 0)
        return;
    if(b[i][j] == 1){
        LCS(i-1, j-1, x, b);
        cout<<x[i];
    }
    else if(b[i][j] == 2)
        LCS(i-1, j, x, b);
    else 
        LCS(i, j-1, x, b);
}

3.3 流水作业调度

要求确定这n个作业的最优加工顺序,使得从第一个作业在机器M1上开始加工,到最后一个作业在机器M2上加工完成所需的时间最少。

FlowShop()函数用于将流水作业的序号进行最优化排序并返回所用时间。

class Jobtype{
public:
    int key;
    int index;
    bool job;
};
bool cmp(Jobtype a,Jobtype b){
    ///升序排序
    return a.key<b.key;
}
int FlowShop(int n,int *a,int *b,int *c){
    Jobtype *d=new Jobtype[n];
    for(int i=0;i<n;i++){
        d[i].index=i;
        d[i].key=a[i]>b[i]?b[i]:a[i];
        d[i].job=a[i]<b[i]?true:false;///返回true和false
    }
     //sort(d,n);//对数组d按关键字升序进行排序
     sort(d,d+n,cmp);//按照c[]中作业时间增序排序
    int j=0,k=n-1;
    for(int i=0;i<n;i++){
        if(d[i].job==true){ ///先把m1的装入最前面,以便于开始执行工作
            c[j++]=d[i].index;
        }
        else{
            c[k--]=d[i].index;///因为是升序,所以m2执行时,应该是先执行大的
        }
    }
    ///上面是对c【i】的一个执行工作的序号的排序
    j=a[c[0]];///m1执行的工作时间
    k=j+b[c[0]];///m2执行的工作时间
    for(int i=1;i<n;i++){
        j+=a[c[i]];///m1开始执行第二个工作的时间
        k=j>k?(j+b[c[i]]):(k+b[c[i]]);
    }
    delete d;
    return k;
}

3.4 0-1背包问题

问 题 的 形 式 描 述 是 : 给 定 c > 0 , w i > 0 , v i > 0 , 1 ≤ i ≤ n , 求 n 元 0 − 1 向 量 ( x 1 , x 2 , … , x n ) , 使 得 : 问题的形式描述是:给定c>0,w_i>0,v_i>0,1≤ i ≤n,求n元0-1向量(x_1, x_2, …, x_n),使得: c0wi0vi01inn01(x1,x2,,xn)使:
∑ i = 1 n w i x i \displaystyle\sum_{i=1}^{n} w_ix_i i=1nwixi ∑ i = 1 n v i x i \displaystyle\sum_{i=1}^{n} v_ix_i i=1nvixi达到最大。

Knapsack()函数用于计算最大容量.

void Knapsack(int v[],int w[],int c,int n,int m[][10])  
{  
    int jMax = min(w[n]-1,c);//背包剩余容量上限 范围[0~w[n]-1]  
    for(int j=0; j<=jMax;j++)  
    {  
        m[n][j]=0;  
    }  
    for(int j=w[n]; j<=c; j++)//限制范围[w[n]~c]  
    {  
        m[n][j] = v[n];  
    }  
    for(int i=n-1; i>1; i--)  
    {  
        jMax = min(w[i]-1,c);  
        for(int j=0; j<=jMax; j++)//背包不同剩余容量j<=jMax<c  
        {  
            m[i][j] = m[i+1][j];//没产生任何效益  
        }  
        for(int j=w[i]; j<=c; j++) //背包不同剩余容量j-wi >c  
        {  
            m[i][j] = max(m[i+1][j],m[i+1][j-w[i]]+v[i]);//效益值增长vi   
        }  
    }  
    m[1][c] = m[2][c];  
    if(c>=w[1])  
    {  
        m[1][c] = max(m[1][c],m[2][c-w[1]]+v[1]);  
    }  
}  

Traceback()函数用于计算是否装入背包

//x[]数组存储对应物品0-1向量,0不装入背包,1表示装入背包  
void Traceback(int m[][10],int w[],int c,int n,int x[])  
{  
    for(int i=1; i<n; i++)  
    {  
        if(m[i][c] == m[i+1][c])  
        {  
            x[i]=0;  
        }  
        else  
        {  
            x[i]=1;  
            c-=w[i];  
        }  
    }  
    x[n]=(m[n][c])?1:0;  
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值