CLRS第十五章思考题5-8

来源:互联网 发布:vue weixin js sdk 编辑:程序博客网 时间:2024/06/08 02:17

思考题15-5

a)这个问题有点类似最长公共子序列,因此类似的定义 Xi=x[1,2...i],Yj=y[1,2...j]。子问题就是确定一个最优操作序列使得 Xi 转换为 Yj,其中 0im,0jn。原始的问题是 XmYn
c[i,j]XiYj 的一个最优解决代价,然后有:
1) 最后一步是复制操作,则必有 x[i]=y[j],子问题就变成 Xi1Yj1XiYj 的最优解一定包括 Xi1Yj1 的最优解。因此有 c[i,j]=c[i1,j1]+cost(copy)

2) 最后一步是替换操作,则必有x[i]y[j],同时假定替换操作不能替换成要被替换的字符本身,比如不能把字符 a 替换成字符 a。所以 c[i,j]=c[i1,j1]+cost(replace)

3) 最后一步是旋转操作,则有 x[i]=y[j1],x[i1]=y[j],同时也隐含了 i,j2。子问题就变成了 Xi2Yj2,此时有 c[i,j]=c[i2,j2]+cost(twiddle)

4) 最后一步是删除操作,对 x,y 没有限制,子问题就变成了 Xi1Yj,得 c[i,j]=c[i1,j]+cost(delete)

5) 最后一步是插入操作,对 x,y 没有限制。子问题就变成了 XiYj1,得 c[i,j]=c[i,j1]+cost(insert)

6) 最后一步是终止操作,我们必须完成XmYn,也就是说必须是 i=m,j=n。终止操作可以看成是多次的删除操作,子问题变成 XiYn,0i<m。得 c[m,n]=min0i<m{c[i,n]+cost(kill)}

最后来处理基本的情况,即 i=0 或者 j=0X0,Y0 都是空串,从 X0Yj 只需插入 j 次即可,所以 c[0,j]=jcost[insert],类似的XiY0 只需删除 i 次即可,c[i,0]=icost[delete]。然后 c[0,0]=0

总结就是如下:

c[i,j]=minc[i,j]=c[i1,j1]+cost(copy)c[i,j]=c[i1,j1]+cost(replace)c[i,j]=c[i2,j2]+cost(teiddle)c[i,j]=c[i1,j]+cost(delete)c[i,j]=c[i,j1]+cost(insert)c[m,n]=min0i<m{c[i,n]+cost(kill)}if x[i]=y[j]if x[i]≠ y[j]if i,j ≥ 2 and x[i]=y[j-1],x[i-1]=y[j]if i=m,j=n

类似 LCS,按行优先开始计算。

EDIT-DISTANCE(x, y,m, n)    let c[0...m, 0...n] and op[0...m, 0...n] be new arrays    for i = 0 to m        c[i, 0] = i·cost(delete)        op[i, 0] = DELETE    for j = 0 to n        c[0, j]  = j cost(insert)        op[0, j]  = INSERT    for i = 1 to m        for j = 1 to n        c[i, j] = ∞         if x[i] == y[j]             c[i, j] = c[i-1, j-1] + cost(copy)            op[i, j] = COPY        if x[i] ≠ y[j] and c[i-1, j-1] + cost(replace) < c[i, j]            c[i, j]  = c[i-1, j-1] + cost(replace)            op[i, j]  = REPLACE(by y[j] )        if i≥ 2 and j≥ 2 and x[i]  == y[j-1] and x[i-1] == y[j]             and c[i-2, j-2 + cost(twiddle) < c[i, j]            c[i, j]  = c[i-2, j-2] + cost(twiddle)            op[i, j]  = TWIDDLE        if c[i-1, j]  + cost(delete) < c[i, j]            c[i, j]  = c[i-1, j]  + cost(delete)            op[i, j]  = DELETE        if c[i, j-1] + cost(insert) < c[i, j]             c[i, j]  = c[i, j-1] + cost(insert)            op[i, j]  = INSERT(y[j])    for i = 0 to m - 1        if c[i, n] + cost(kill) < c[m, n]            c[m, n] = c[i, n] + cost(kill)            op[m, n] = KILL i    return c and op

时空复杂度都是 Θ(mn),若要保存 KILL 操作,还需要保存 killed 操作的下标 i 来帮助我们重建最优操作序列。

OP-SEQUENCE(op, i, j)    if i == 0 and j == 0        return    if op[i, j] == COPY or op[i, j] == REPLACE        i' = i-1        j' = j-1    elseif op[i, j] == TWIDDLE        i' = i-2        j' = j-2    elseif op[i, j] == DELETE        i' = i-1        j' = j    elseif op[i, j] == INSERT // don’t care yet what character is inserted        i' = i        j' = j-1    else // must be KILL, and must have i = m and j = n        let op[i, j]  == KILL k        i' = k        j' = j    OP-SEQUENCE(op, i', j')    print op[i, j] 

b)只允许下面四种操作,其余两种操作禁止。
cost(copy) = -1 ;
cost(replace) = +1 ;
cost(delete) = +2 ;
cost(insert) = +2 ;

因此 DNA 对齐问题就转换为求最小化编辑距离代价的负数。

思考题15-6

使用动态规划,令 c[x] 表示员工 x 的交际评分,我们希望找出所有员工的子集 S 使得当 xS  parent[x]S 时有最大的 xSc[x]
M(x) 表示以 x 为根节点的子树且 x 被邀请时的最大交际评分,M(x) 表示以 x 为根节点的子树且 x 不被邀请时的最大交际评分,然后得到:

M(x)=c[x]+y(parent[y]=x)M(y)M(x)=y(parent[y]=x)max{M(y),M(y)}

上面的第一个式子表示员工 x 的交际评分以及 x 的直接下属 y 不被邀请时以 y 为根节点的子树的交际评分;第二个式子表示从员工 x 的直接下属(不包括 x)中邀请以员工 y 为根节点的子树的交际评分的最大值。

solve(x)    M(x) = c[x]    M'(x) = 0    y = left-child[x]    while y ≠ NIL        do solve(y)            M(x) = M(x) + M'(y)            M'(x) = M'(x) + max{M(y),M'(y)}            y = right-child[y]

以公司主席开始调用solve函数。接下来决定邀请人员名单。

invite(x)    if M(x) > M'(x)        then invite x to the party            for all grandchildren y of x                invite(y)    else         for all children y of x            invite(y)

最后的时间复杂度就是 O(n)

思考题15-7

略,提供一个链接,有兴趣的可以看一看这里写链接内容

思考题15-8

a) 令当前被删除的是 A[i,j],则第 i+1 行应该怎么删除像素呢?当 A[i,j] 处于列边界时(i=1i=n),比如 i=1,此时只有两种选择 A[i+1,j]A[i+1,j+1]。其他情况下都可以有三种删除像素的选择:A[i+1,j1],A[i+1,j],A[i+1,j+1]。也就是说对某一行的像素 p 来说,下一行的选择至少有两种。令 T(i) 表示从第 1 行到第 i 行可能的接缝数。当 i=1T(1)=n。当 i>n 时有:T(i)2T(i1),很容易计算得 T(i)=n2i1。因此 T(m)=n2m1

b) 令 disr[i,j] 为从 A[i,j] 开始的所有接缝中选择出来的接缝破坏度之和最小的一条接缝的值。基础情况是 disr[m,j]=d[m,j],j=1,2...n,递归情况下有:disr[i,j]=d[i,j]+minkK{disr[i+i,j+k]}K 的取值如下:

K={0,1}{1,0,1}{1,0}if j=1if 1<j<mif j=m

因此我们只用得到最小化的 disr[1,j] 即可。

COMPRESS-IMAGE(d)    m = d.rows    n = d.columns    let disr[1..m, 1..n] and next[1..m, 1..n] be new tables    for j = 1 to n        disr[m, j] = d[m, j]    for i = m - 1 downto 1        for j = 1 to n            low = max(-1, 1-j)            high = min(1, n-j)            disr[i, j] = ∞            for k = low to high                if disr[i + 1, j + k] < disr[i, j]                     disr[i, j] = disr[i + 1, j + k]                    next[i, j] = j + k            disr[i, j] = disr[i, j] + d[i, j]            val = ∞            start = 1            for j = 1 to n                if disr[1, j] < val                    val = disr[1, j]                    start = j            print “The minimum value of the disruptive measure is ” val            for i = 1 to m                print “cut point at ” (i, start)                start = next[i, start]

最后时间和空间复杂度都是 O(mn)

0 0