算法设计与分析——动态规划(二)

只是答案的搬运工~

3.1

给定一个浮点数序列(可能有正数、0和负数),设计一个动态规划算法,求出一个最大的连续子序列中浮点数乘积。
(1)简明的写出问题的递推方程;
(2)描述算法伪代码;
(3)分析算法的时间复杂度。

dp1[i]:以第i个数结尾的连续子序列最大乘积
dp2[i]:以第i个数结尾的连续子序列最小乘积

转移方程:
dp1[i]=max(data[i],dp1[i-1]*data[i],dp2[i-1]*data[i]);
dp2[i]=min(data[i],dp1[i-1]*data[i],dp2[i-1]*data[i]);
最后遍历dp1得到最大值即为答案。

#include<stdio.h>
double max(double a,double b){return a>b?a:b;}
double min(double a,double b){return a<b?a:b;}
double dp1[100001];
double dp2[100001];
double data[100001];
double helper(double data[],int n)
{
  dp1[0]=data[0];
  dp2[0]=data[0];
  for(int i=1;i<n;i++)
  {
	  dp1[i]=max(data[i],max(dp1[i-1]*data[i],dp2[i-1]*data[i]));
	  dp2[i]=min(data[i],min(dp1[i-1]*data[i],dp2[i-1]*data[i]));
  }
  double ans=dp1[0];
  for(int i=1;i<n;i++)
  {
	  ans=max(ans,dp1[i]);
  }
  return ans;
}

int main(void)
{
    int i,n;
    while(scanf("%d",&n)!=EOF)
    {
        for(i=0; i<n; ++i)
        {
            scanf("%lf", &data[i]);
        }
        double ans = helper(data, n);
        printf("%lf\n",ans);
    }
    return 0;
}

3.2

已知一个矩形区域被划分为N*M个小矩形格子,在格子(i,j)中有A[i][j]个苹果。现在从左上角的格子(1,1)出发,要求每次只能向右走一步或向下走一步,最后到达(N,M),每经过一个格子就把其中的苹果全部拿走。设计一个动态规划算法,找出能拿到最多苹果数的路线。
(1)简明的写出问题的递推方程;
(2)描述算法伪代码;
(3)分析算法的时间复杂度。
(4)将原问题变为“从起点出发,用相同的方法走两次,但是两条路线中除了起点和终点外不经过任何同一节点”,简明写出动态规划解决这个新问题的思路和递推方程。

转移方程:d[i,j]=max{d[i-1,j],d[i,j-1]}+a[i,j]
同矩阵链乘
(4)第一次经过的格子(i,j)把a[i,j]置为0.

3.3

考虑三个字符串X,Y,Z 的最长公共子序列LCS(X,Y,Z)。
(1)寻找反例X,Y,Z 使得LCS(X,Y,Z)≠LCS(X, LCS(Y,Z));
(2)设计动态规划算法计算X,Y,Z 的最长公共子序列,分析算法的时间复杂度。

(1)X:c Y:abc Z:cab
(2)LCS(i,j,k)=LCS(i-1,j-1,k-1)+1 (if X[i]==Y[j]==Z[k])
LCS(i,j,k)=max{LCS(i-1,j,k),LCS(i,j-1,k),LCS(i,j,k-1)}

3.4

令I1, …, In是n个区间,其中任一区间Ii=(ai,bi),假设这些区间按照bi从小到大排序,每一个区间有一个权重vi,考虑如下两个问题:
区间安排问题 P1: 找到最大数量互不相交的区间,例如,对于四个区间I1 = (1,2); I2 = (2,3); I3 = (1,4); I4 = (4,5),一个解是{I1, I2, I4}
加权任务安排问题P2: 找一个互不相交区间的集合,使得这些区间的权重之和最大,例如I1 = (1,2), v1=0.9; I2 = (2,3), v2=0.5; I3 = (1,4), v3=4; I4 = (4,5), v4=2,解是{I3, I4}。
(1) 给出解决问题P1的线性时间算法。
(2) 给出解决问题P2的动态规划算法,要求写出递归方程和伪代码,并分析算法时间复杂性。
(2)dp[i]=max{dp[j]}+vi
vi,v(j)不相交 j=1,2,…,i-1
时间复杂度为O(n^2)

3.5

编辑距离问题
© 考虑编辑距离的一种变形,其允许在字符串后无代价地插入无限多个字符,该编辑距离描述为:
ed’(A, B)=min{ed(A, C)|C是B的前缀}, 其中函数ed()是普通的编辑距离函数。根据要求设计算法,要求算法的时间复杂性都是O(|A||B|)
(1) 设计算法,对于给定的字符串A和B,计算ed’(A, B);
(2) 设计算法,对于给定的字符串A,B和整数k,判定是否B存在某个后缀B’,满足ed’(A, B’)k。
(1)

for( i=0 to |A| )
    dp[i][0] = i;
for( j=0 to |B| )
    dp[0][j] = j;
for( i=1 to |A| )
    for( j=1 to |B| )
        dp[i][j] = min{
            dp[i-1][j]+1,
            dp[i][j-1]+1,
            dp[i-1][j-1]+( A[i]!=B[j] )
        }
ans = INF;
for( j=0 to |B| )
    ans = min(ans,dp[ |A| ][j]);

(2)把A,B串翻转为A1,B1,求ed’(A1,B1),则ed’(A1,B1)即为问题所求。

reverse( A );

reverse( B );

for( i=0 to |A| )

    dp[i][0] = i;

for( j=0 to |B| )

    dp[0][j] = j;

for( i=1 to |A| )

    for( j=1 to |B| )

        dp[i][j] = min{

            dp[i-1][j]+1,

            dp[i][j-1]+1,

            dp[i-1][j-1]+( A[i]!=B[j] )

        };

for( j=0 to |B| )

    ans = min(ans,dp[ |A| ][j]);

3.6

T1和T2是两棵有序树,其中每个结点都有一个标签,考虑树上的三种操作,删除一个子树、插入一个子树和更改一个结点的标签,请设计一个算法,求得从T1变化到T2所需要的最少操作数,要求写出递推方程,程序伪代码并分析时间复杂性。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值