【算法设计与分析】作业2:动态规划

这篇具有很好参考价值的文章主要介绍了【算法设计与分析】作业2:动态规划。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

题目1 最长递增子序列

  1. 最长递增⼦序列(LIS)

    1. 编程实现求解最长递增⼦序列的三种动态规划算法(⼀些细节请参考课件)

      1.1 算法1:令 L ( k ) L(k) L(k)表示 s [ 1.. n ] s[1..n] s[1..n]中以 s [ k ] s[k] s[k]结尾的LIS的长度,原问题即求解 max ⁡ 1 ≤ k ≤ n L ( k ) \max_{1\le k\le n}L(k) max1knL(k)

      1.2 算法2:令 L ( i , j ) L(i,j) L(i,j)表示 s [ 1.. n ] s[1..n] s[1..n]中每个元素都⼤于 s [ i ] s[i] s[i]的LIS的长度,再令 s [ 0 ] = − ∞ s[0]=-\infty s[0]=,原问题即求
      L ( 0 , 1 ) L(0,1) L(0,1)

      1.3 算法3:构建数组 L L L,令 L ( k ) L(k) L(k)表示 s [ 1.. n ] s[1..n] s[1..n]中⻓度为 k k k且末尾元素最⼩的递增⼦序列的末尾元素,原问题即求解 L L L的长度

  2. 上述算法仅仅求出LIS的长度,请对其改进以求出具体的序列。⾸先给出每种改进算法的基本思路,然后给出伪代码,并分析算法的时空复杂度。

算法1

基本思路

1 建立递归关系

1.1 要求解的子问题:令 L ( k ) L(k) L(k)表示 s [ 1.. n ] s[1..n] s[1..n]中以 s k s_k sk结尾的 L I S LIS LIS的具体序列。

1.2 如何基于子问题求解原问题:根据 L ( i ) ( 1 ≤ i ≤ k − 1 ) L(i) (1\le i \le k-1) L(i)(1ik1),找到某个下标 i i i,这个下标的值 s i s_i si小于 s k s_k sk 且这个下标对应的具体序列 L ( i ) L(i) L(i)的长度最长。

1.3 基本情况:原始算法中当 k = 1 k=1 k=1时, L ( k ) = 1 L(k)=1 L(k)=1。改进算法中同样认定 k = 1 k=1 k=1 L ( k ) = 1 L(k)=1 L(k)=1且具体序列中只有 s 1 s_1 s1

1.4 递归情况:记原始算法中 L I S LIS LIS长度为 L e n ( k ) Len(k) Len(k),本改进算法中具体序列为 L ( k ) L(k) L(k)。根据原始算法中的递归关系,找到使得原始算法中递归关系 L e n ( k ) = max ⁡ { 1 , max ⁡ 1 ≤ i ≤ k − 1 { L e n ( i ) + 1 ∣ s k > s i } } Len(k)=\max\{1,\max_{1\le i \le k-1}\{Len(i)+1|s_k>s_i\}\} Len(k)=max{1,max1ik1{Len(i)+1∣sk>si}}中满足 s k > s i s_k>s_i sk>si的对应下标 i i i。若 L e n ( k ) = 1 Len(k)=1 Len(k)=1,则认为:以 s k s_k sk结尾的 L I S LIS LIS的具体序列有且只有 s k s_k sk一项,即 L ( k ) = [ s k ] L(k)=[s_k] L(k)=[sk]。若 L e n ( k ) ≠ 1 Len(k)\ne 1 Len(k)=1 ,根据 max ⁡ 1 ≤ i ≤ k − 1 { L e n ( i ) + 1 ∣ s > s i } } \max_{1\le i \le k-1}\{Len(i)+1|s_>s_i\}\} max1ik1{Len(i)+1∣s>si}}的计算情况,可找到以 s k s_k sk为结尾的具体序列中的序列前一项 s i s_i si,即: L ( k ) = [ L ( i ) , s k ] L(k)=[L(i),s_k] L(k)=[L(i),sk]

2 自底向上求解

2.1 备忘录形式:开辟一个新的数组 L a s t [ 1.. n ] Last[1..n] Last[1..n] L a s t k Last_k Lastk表示使得 L e n ( k ) = max ⁡ { 1 , max ⁡ 1 ≤ i ≤ k − 1 { L e n ( i ) + 1 ∣ s k > s i } } Len(k)=\max\{1,\max_{1\le i \le k-1}\{Len(i)+1|s_k>s_i\}\} Len(k)=max{1,max1ik1{Len(i)+1∣sk>si}}中满足 s k > s i s_k>s_i sk>si的对应下标 i i i,此时记录 L a s t k = i Last_k=i Lastk=i。即: L a s t k Last_k Lastk表示以 k k k为结尾的LIS的具体序列前一项对应的下标值。若 L a s t k = k Last_k=k Lastk=k,则这个序列没有前一项。

2.2 子问题求解顺序:按自底向上,从左至右的顺序遍历 s [ 1.. n ] s[1..n] s[1..n],求解序列长度 L e n ( k ) Len(k) Len(k)的同时更新对应的 L a s t k Last_k Lastk。在所有 L e n ( k ) Len(k) Len(k)求解完成后,找到 max ⁡ 1 ≤ k ≤ n L e n ( k ) \max_{1\le k\le n}Len(k) max1knLen(k)的对应 k k k,其为具体序列 L ( k ) L(k) L(k)的最后一项。根据 L a s t Last Last数组一步步找到前一项,头插入到 L ( k ) L(k) L(k)中,并使得 k = L a s t k k=Last_k k=Lastk。重复此过程,直到 L a s t i = i Last_i=i Lasti=i对应的 s i s_i si为序列第一项。

2.3 时空复杂度分析:外层循环遍历 s 1.. n s_{1..n} s1..n,需要 O ( n ) O(n) O(n)时间。内层循环遍历 L e n ( 1.. k ) Len(1..k) Len(1..k),需要 O ( n ) O(n) O(n)时间。一共两层循环,时间复杂度 O ( n 2 ) O(n^2) O(n2)。空间复杂度上,开辟的数组 L a s t Last Last L e n Len Len和用于存储最终序列的 L L L都是一维数组,空间复杂度 O ( n ) O(n) O(n)

伪代码

【算法设计与分析】作业2:动态规划,算法,动态规划
时间复杂度: O ( n 2 ) O(n^2) O(n2)。空间复杂度: O ( n ) O(n) O(n)

代码

int lis_dp1(const vector<int> &s, int n) {
    vector<int> L(n + 2);
    for (int i = 1; i <= n; i++) 
        L[i] = 1;
    for (int i = 1; i <= n; i++) {
        for (int j = 1; j < i; j++) {
            if (s[i] > s[j])
                L[i] = max(L[i], L[j] + 1);
        }
    }
    int res = 0;
    for (int i = 1; i <= n; i++)
        res = max(res, L[i]);
    return res;
}

vector<int> find_lis_dp1(const vector<int> &s, int n) {
    vector<int> L(n + 2);
    vector<int> last(n + 2);
    for (int i = 1; i <= n; i++) {
        L[i] = 1;
        last[i] = i;
    }
    for (int i = 1; i <= n; i++) {
        for (int j = 1; j < i; j++) {
            if (s[i] > s[j]) {
                if (L[j] + 1 > L[i]) {
                    L[i] = L[j] + 1;
                    last[i] = j;
                }
            }
        }
    }
    int residx = 0;
    int res = 0;
    for (int i = 1; i <= n; i++) {
        if (L[i] > res) {
            res = L[i];
            residx = i;
        }
    }
    vector<int> resvec;
    int i = residx;
    while (i != last[i]) {
        resvec.insert(resvec.begin(), s[i]);
        i = last[i];
    }
    resvec.insert(resvec.begin(), s[i]);
    return resvec;
}

算法2

基本思路

1 建立递归关系

1.1 要求解的子问题: L e n ( i , j ) Len(i,j) Len(i,j)表示 s j . . n s_{j..n} sj..n中每个元素都大于 s i s_i si L I S LIS LIS的长度。令 L ( i , j ) L(i,j) L(i,j)表示 s j . . n s_{j..n} sj..n中每个元素都大于 s i s_i si的具体序列。

1.2 如何基于子问题求解原问题:令 s 0 = − ∞ s_0=-\infty s0=,原问题即求解 L e n ( 0 , 1 ) Len(0,1) Len(0,1)的值和 L ( 0 , 1 ) L(0,1) L(0,1)的具体序列。

1.3 基本情况:若 j > n j>n j>n L e n ( i , j ) = 0 Len(i,j)=0 Len(i,j)=0,此时 L ( i , j ) = ∅ L(i,j)=\emptyset L(i,j)=

1.4 递归情况:
L e n ( i , j ) = { 0 i f   j > n L e n ( i , j + 1 ) i f   s i ≥ s j max ⁡ { L e n ( i , j + 1 ) 1 + L e n ( j , j + 1 ) o t h e r w i s e Len(i,j)=\begin{cases} 0&\mathrm{if}\ j>n\\ Len(i,j+1)&\mathrm{if}\ s_i\ge s_j\\ \max\begin{cases} Len(i,j+1)\\1+Len(j,j+1) \end{cases}&\mathrm{otherwise} \end{cases} Len(i,j)= 0Len(i,j+1)max{Len(i,j+1)1+Len(j,j+1)if j>nif sisjotherwise
对于第 i i i个元素,从 L e n ( i , i + 1 ) Len(i,i+1) Len(i,i+1)开始向右查找,找到令 L e n ( i , j ) = = L e n ( i , j + 1 ) + 1 Len(i,j)==Len(i,j+1)+1 Len(i,j)==Len(i,j+1)+1 j j j,则 L ( i , i + 1 ) L(i,i+1) L(i,i+1)的具体序列不仅包括当前项 s i s_i si,而且下一项就是 s j s_j sj。从 L e n ( 0 , 1 ) Len(0,1) Len(0,1)开始重复这一过程,找到具体序列。

2 自底向上求解

2.1 备忘录形式:改进算法时,不开辟新的数组,只使用 L e n ( i , j ) Len(i,j) Len(i,j)表示 s 1.. n s_{1..n} s1..n中每个元素大于 s i s_i si L I S LIS LIS的长度。

2.2 子问题求解顺序:自底向上求解 L e n Len Len数组。在求解 L e n Len Len这个二维数组的过程中,按从右向左、从下至上的顺序遍历。在求解 L e n Len Len数组完成后,令 i = 0 i=0 i=0,从第 0 0 0个元素 s 0 = − ∞ s_0=-\infty s0=开始,使用类似于双指针的算法,遍历 L e n ( i , j ) Len(i,j) Len(i,j)数组的列,找到使得 L e n ( i , j ) = = L e n ( i , j + 1 ) + 1 Len(i,j)==Len(i,j+1)+1 Len(i,j)==Len(i,j+1)+1的对应 j j j,则说明具体序列 L L L中含有 s j s_j sj,将 s j s_j sj加入到具体序列 L L L中。令 i ← j i\gets j ij,重复上述求解过程:根据 L e n ( i , j ) Len(i,j) Len(i,j)的值不断找到具体序列中的下一个元素,直到数组被遍历到 L e n ( i , j ) = 0 Len(i,j)=0 Len(i,j)=0的位置。

2.3 时空复杂度分析:有 O ( n 2 ) O(n^2) O(n2)个子问题,求解原序列的时间复杂度为 O ( n ) O(n) O(n)。时空复杂度均为 O ( n 2 ) O(n^2) O(n2)

伪代码

【算法设计与分析】作业2:动态规划,算法,动态规划
时间复杂度、空间复杂度都是 O ( n 2 ) O(n^2) O(n2)

代码

int lis_dp2(const vector<int> &s, int n) {
   // insert code here...
   vector<vector<int>> L(n + 2, vector<int>(n + 2, 0));
   for (int i = n; i >= 0; i--) {
       for (int j = n; j >= i; j--) {
           if (s[i] >= s[j]) {
               L[i][j] = L[i][j + 1];
           } else {
               L[i][j] = max(L[i][j + 1], 1 + L[j][j + 1]);
           }
       }
   }
   return L[0][1];
}
// revised algorithm 2 to compute a LIS
vector<int> find_lis_dp2(const vector<int> &s, int n) {
   // insert code here...
   vector<vector<int>> L(n + 2, vector<int>(n + 2, 0));
   for (int i = n; i >= 0; i--) {
       for (int j = n; j >= i; j--) {
           if (s[i] >= s[j]) {
               L[i][j] = L[i][j + 1];
           } else {
               L[i][j] = max(L[i][j + 1], 1 + L[j][j + 1]);
           }
       }
   }
   vector<int> res;
   int cur = 0;
   int i = 1;
   while (L[cur][i] != 0) {
       int curlen = L[cur][i];
       while (i <= n && curlen == L[cur][i]) 
           i++;
       i--;
       res.push_back(s[i]);
       cur = i;
   }
   return res;
}

算法3

基本思路

1.建立递归关系

1.1 要求解的子问题:令 L ( k ) L(k) L(k)表示 s 1.. n s_{1..n} s1..n中长度为 k k k且末尾元素最小的递增子序列的。 L ( k ) . l a s t L(k).last L(k).last表示该序列最后的元素。

1.2 如何基于子问题求解原问题:因为 L ( 1 ) . l a s t < L ( 2 ) . l a s t < . . . < L ( k ) . l a s t L(1).last<L(2).last<...<L(k).last L(1).last<L(2).last<...<L(k).last,所以对于长度小于 n n n的序列,可以计算所有的 L ( k ) L(k) L(k)的具体序列,并存储。

1.3 基本情况:对于长度为1的序列, L ( 1 ) = [ s 1 ] L(1)=[s_1] L(1)=[s1]

1.4 递归情况:
从左至右遍历原序列 s 1.. n s_{1..n} s1..n,对于当前元素 s i s_i si,在 L ( k ) . l a s t L(k).last L(k).last构成的有序数组中使用二分法查找插入位置 k ′ k' k。若 k ′ k' k L ( k ) . l a s t L(k).last L(k).last数组最后,则 L ( k + 1 ) = [ L ( k ) , s i ] L(k+1)=[L(k),s_i] L(k+1)=[L(k),si],且 L ( k + 1 ) . l a s t ← s i L(k+1).last\gets s_i L(k+1).lastsi。否则, L ( k ′ ) . l a s t ← s i L(k').last\gets s_i L(k).lastsi,但原具体序列 L ( k ) L(k) L(k)不变。

2.自底向上求解

2.1 备忘录形式:开辟一个数组 L i d x Lidx Lidx,表示序列 L L L内各个元素的下标。开辟一个数组 p r e v prev prev p r e v i = j prev_i=j previ=j表示:原序列第 i i i个元素 s i s_i si若在最终的具体序列中,则其上一项的下标是 j j j,即其上一项 s j s_j sj也在具体序列中。通过 p r e v prev prev这个备忘录,找到每个元素的前置元素。存储具体序列的最后一项元素 i b e g i n i_{begin} ibegin。用res存储最终的具体序列。

2.2 子问题求解顺序:在原算法中,按自底向上的顺序,在更新 L L L数组的同时,更新对应的 L i d x Lidx Lidx p r e v prev prev数组。在将 L L L求解完成后,求解原序列:根据LIS具体序列中最后一项的下标 i b e g i n i_{begin} ibegin,得知具体序列最后一项含 s i s_i si,根据 p r e v i prev_i previ,得知具体序列中 s i s_i si的上一项为 s p r e v i s_{prev_i} sprevi,并令 i = p r e v i i=prev_i i=previ。以此种方式循环,直到 i = p r e v i i=prev_i i=previ时的 s i s_i si为序列第一项。

2.3 时空复杂度分析:完整遍历数组需要 O ( n ) O(n) O(n)的时间复杂度,每次遍历时查找并修改需要 O ( log ⁡ n ) O(\log n) O(logn)的时间复杂度。总时间复杂度为 O ( n log ⁡ n ) O(n\log n) O(nlogn)。需要开辟多个长度为 n n n的一维数组,总空间复杂度为 O ( n ) O(n) O(n)

伪代码

【算法设计与分析】作业2:动态规划,算法,动态规划
时间复杂度 O ( n log ⁡ n ) O(n\log n) O(nlogn),空间复杂度 O ( n ) O(n) O(n)

题目2 蒙德里安的梦想

给定⼀个 3 × n 3\times n 3×n的棋盘, 设计⼀个动态规划算法计算有多少种使⽤ 1 × 2 1\times 2 1×2的骨牌进行完美覆盖的⽅案。完美覆盖是指没有未覆盖的⽅格,也没有堆叠或者悬挂在棋盘外的⻣牌。

基本思路

1.建立递归关系

1.1 要求解的子问题:令 f ( i , j ) f(i,j) f(i,j)表示前 i − 1 i-1 i1列的骨牌已经放置好,且从第 i − 1 i-1 i1列伸出到第 i i i列的状态是 j j j的所有方案数。记 f ( n , 0 ) f(n,0) f(n,0)为最终的解。

1.2 如何基于子问题求解原问题:在所有横着的小骨牌被放置完成后,只要纵向有两个连续的空格,则可以在纵向的两个连续空格中放置骨牌。所以,记:在某一列中,纵向有0个或2个(偶数个)连续空格的所有骨牌覆盖状态为“有效状态”。将“有效状态”记录进数组 s t st st中。基于上一列的状态,横放新的小骨牌,就可以转移进入到下一列的状态。在转移时,当前列与下一列不能发生冲突。也需要判断放置后是否会进入无效状态。

如图所示,以红色表示没有被覆盖的块,以黄色表示上一列第 i − 1 i-1 i1列中已经被覆盖有骨牌的块。各个原状态在图中最左侧一列。各个状态能转移进入的下一有效状态在图右侧。通过横放新的骨牌,才能转移进入下一状态。新放的骨牌以绿色表示。

在有效状态中,存在偶数个(包括0)个连续的未被覆盖的块,可以竖向放置骨牌。因此,所有能横向放置骨牌的方案数即为总方案数。在最后一列需要读取各个有效状态的方案数。但是,计算中间列 i ( 1 < i < n ) i(1<i<n) i(1<i<n)的过程中,中间列 i i i不一定是有效状态。
【算法设计与分析】作业2:动态规划,算法,动态规划
1.3 基本情况:
不放置任何骨牌时, f 0 , 0 = 1 f_{0,0}=1 f0,0=1

1.4 递归情况:
在第 i i i列,遍历所有状态 j j j。考虑所有与 j j j不冲突且有效的状态 k k k,则 f ( i , j ) = ∑ k f ( i − 1 , k ) f(i,j)=\sum_kf(i-1,k) f(i,j)=kf(i1,k)

2.自底向上求解

2.1 备忘录形式: f f f是一个二维数组。在 f ( i , j ) f(i,j) f(i,j)中, j j j是一个二进制数,由于棋盘行数为3,所以 j ∈ { 0 , 1 , 2 , 3 , 4 , 5 , 6 , 7 } j\in \{0,1,2,3,4,5,6,7\} j{0,1,2,3,4,5,6,7}。根据二进制的位,位为0表示当前位没有被覆盖方块,位为1表示当前位被覆盖方块。在基于子问题求解原问题时,判断当前列状态 x x x与下一列状态 y y y是否在横行产生冲突,只需要通过位运算 x & y x\&y x&y x & y = 0 x\&y=0 x&y=0的情况表示没有冲突,可以转移。提前预处理“有效状态”进入数组 s t st st中, s t j = 1 st_j=1 stj=1表示 j j j状态有效。有效状态中的纵向存在0个或2个连续空格。通过 s t x ∣ y st_{x|y} stxy读取 x x x状态转换到 y y y状态时是否会导致出现没有偶数个连续空格的无效状态情况。

2.2 子问题求解顺序:以自底向上的顺序,从左至右以 i i i增长的方式遍历 f ( i , j ) f(i,j) f(i,j)

2.3 时空复杂度分析:内层循环中,状态数 2 3 = 8 2^3=8 23=8为常数。外层循环中,遍历 f ( i , j ) f(i,j) f(i,j)第一维的时间复杂度为 O ( n ) O(n) O(n)。则总体时间复杂度为 O ( n ) O(n) O(n)。虽然 f ( i , j ) f(i,j) f(i,j)是一个二维数组,但是第二维状态数只有 2 3 = 8 2^3=8 23=8是常数。所以总体空间复杂度为 O ( n ) O(n) O(n)

伪代码

【算法设计与分析】作业2:动态规划,算法,动态规划

题目3(Jon Kleinberg算法设计 习题)

We are given a checkerboard which has 4 rows and columns, and has an integer written in each square. We are also given a set of 2 n 2n 2n pebbles, and we want to place some or all of these on the checkerboard (each pebble can be placed on exactly one square) so as to maximize the sum of the integers in the squares that are covered by pebbles. There is one constraint: for a placement of pebbles to be legal, no two of them can be on horizontally or vertically adjacent squares (diagonal adjacency is fine).
给定一个有4行、 n n n列的棋盘,每个棋盘格中有一个数。给定 2 n 2n 2n个鹅卵石,我们想放置部分或所有鹅卵石到棋盘中,每个鹅卵石都只能覆盖一个格子,将覆盖住的数的总和最大化。只有一个限制:在合法的放置中,没有两个格子在水平或垂直方向相邻。对角线方向相邻是合法的。

第一问

1.1. Determine the number of legal patterns that can occur in any column (in isolation, ignoring the pebbles in adjacent columns) and describe these patterns.
决定合法的放置模式数量,可以出现在任意一列中。(孤立的,忽略相邻列的鹅卵石)。描述这些模式。
记行下标从0开始。
什么都不放置。
只放置第0行。
只放置第1行。
只放置第2行。
只放置第3行。
放置第0行和第2行。
放置第0行和第3行。
放置第1行和第3行。
若使用二进制进行描述,某一位为0表示不放置,某一位为1表示放置,则合法的放置有:0、1、2、4、5、8、9、10。一共有8种模式。
合法的放置模式数量共有8种。

第二问

Call two patterns compatible if they can be placed on adjacent columns to form a legal placement. Let us consider subproblems consisting of the first k k kcolumns ( 1 ≤ k ≤ n ) 1\le k\le n) 1kn). Each subproblem can be assigned a type, which is the pattern occurring in the last column.
Using the notions of compatibility and type, give an O ( n ) O(n) O(n)-time dynamic programming algorithm for computing an optimal placement.
如果两个模式能放在相邻列,则把两个模式称作“兼容”。考虑子问题只包括前 k k k ( 1 ≤ k ≤ n ) (1\le k\le n) (1kn)。每个子问题都被赋予一个类型,即最后一列的模式。
根据类型之间的兼容性,给出一个 O ( n ) O(n) O(n)的动态规划算法用于计算最优解。

基本思路

1.建立递归关系
1.1 要求解的子问题:前 i i i ( 1 ≤ i ≤ n ) (1\le i \le n) (1in),其中第 i i i列的摆放方案是 j j j,得到的最优摆放方案的值,记结果为 f ( j , i ) f(j,i) f(j,i)

1.2 如何基于子问题求解原问题:对于第 i i i列的方案 j j j,遍历所有与 j j j方案兼容的方案 k k k j j j k k k都是二进制编码,某一位为1表示当前位被覆盖,通过所有 f ( k , i − 1 ) f(k,i-1) f(k,i1)的值,加上当前列覆盖住的值,得到当前列的值 f ( j , i ) f(j,i) f(j,i)

模式的自兼容情况可以通过位运算得到。模式间的兼容情况也可以通过位运算、两两遍历所有自兼容的模式得到。

0模式兼容0、1、2、4、5、8、9、10模式

1模式兼容0、2、4、8、10模式

2模式兼容0、1、4、5、8、9模式

4模式兼容0、1、2、8、9、10模式

5模式兼容0、2、8、10模式

8模式兼容0、1、2、4、5模式

9模式兼容0、2、4模式

10模式兼容0、1、4、5模式
【算法设计与分析】作业2:动态规划,算法,动态规划
1.3 基本情况:在第0列, i = 0 i=0 i=0,不覆盖任何鹅卵石时,方案的二进制编码 j = 0 j=0 j=0 f ( 0 , 0 ) = 0 f(0,0)=0 f(0,0)=0

1.4 递归情况:记当前列在 k k k方案下覆盖住的值为 s u m sum sum,则对于所有与 k k k兼容的 j j j,有 f ( j , i ) = max ⁡ ( s u m + f ( k , i − 1 ) ) f(j,i)=\max (sum + f(k,i-1)) f(j,i)=max(sum+f(k,i1))

2.自底向上求解

2.1 备忘录形式:用数组 f ( j , i ) f(j,i) f(j,i)表示第 i i i j j j模式下取得的最大值。用数组 p p p记录列内自兼容的模式的序号。用数组 c o m p a t i b l e compatible compatible记录每个模式能兼容的模式的序号。用数组 s u m ( j , i ) sum(j,i) sum(j,i)表示 j j j模式下 i i i列的值。

2.2 子问题求解顺序:以自底向上的顺序,根据 f ( j , i − 1 ) f(j,i-1) f(j,i1)求解 f ( j , i ) f(j,i) f(j,i)

2.3 时空复杂度分析:时间复杂度:外层循环遍历每一列, O ( n ) O(n) O(n)。内层循环遍历每种情况。但最多存在8种列内自兼容的情况,列间兼容情况也最多不超过8种。所以总体时间复杂度是 O ( n ) O(n) O(n)。空间复杂度:需要一个行数为8,列数为 n n n的二维数组,空间复杂度为 O ( n ) O(n) O(n)

伪代码

【算法设计与分析】作业2:动态规划,算法,动态规划文章来源地址https://www.toymoban.com/news/detail-833242.html

到了这里,关于【算法设计与分析】作业2:动态规划的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

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

    任务描述 沿着河岸摆放 N 堆石子,现要将石子有次序地合并成一堆,规定每次只能选相邻的 2 堆合并成新的一堆,并将新的一堆的石子数,记为该次合并的得分。 例如: 4 堆石子 4,5,9,4 ,可以按 (((4,5),9),4) 合并。 第一次合并得分是 9 分,合并之后石子堆是 9,9,4 第二次合并得

    2024年02月08日
    浏览(51)
  • 算法设计与分析—动态规划例题

    题目描述 求FIB数列第n项的值 输入 输入一个整数n,表示需要输出FIB数列第n项的值 输出 输出FIB数列第n项的值 样例输入  复制 样例输出  复制 提示 题目描述 长江游艇俱乐部在长江上设置了n (n=10)个游艇出租站1,2,…,n。游客可在这些游艇出租站租用游艇,并在下游的

    2024年04月13日
    浏览(44)
  • 【算法分析与设计】动态规划(上)

       理解动态规划算法的概念 。    掌握动态规划算法的基本要素 :   (1) 最优子结构性质   (2) 重叠子问题性质   掌握设计动 态规划算法的步骤 :   (1) 找出最优解的性质,并刻划其结构特征 。   (2) 递归地定义最优值 。   (3) 以自底向上的方式计算

    2024年02月08日
    浏览(47)
  • 算法分析与设计---分治+动态规划

    1.分治法 适用条件: 问题规模缩小到一定程度容易求解 问题可以分解为若干个规模较小的 相同 子问题,即问题具有最优子结构( 使用分治法前提 ) 可以利用子问题的解合并为该问题的解( 决定是否使用分治法 ) 各个子问题 相互独立 ,即子问题之间不包含公共子问题(

    2024年02月07日
    浏览(45)
  • 【算法分析与设计】动态规划(下)

      若给定序列X={x1,x2,…,xm},则另一序列Z={z1,z2,…,zk},是X的 子序列 是指 存在一个严格递增下标序列{i1,i2,…,ik}使得对于所有j=1,2,…,k有:zj=xij 。例如,序列Z={B,C,D,B}是序列X={A,B,C,B,D,A,B}的子序列,相应的递增下标序列为{2,3,5,7}。   给定2个序列X和Y,当另

    2024年02月08日
    浏览(51)
  • 算法设计与分析 实验三 动态规划

    1.打家劫舍:  给定一个代表每个房屋存放金额的非负整数数组,计算你 不触动警报装置的情况下 ,一夜之内能够偷窃到的最高金额。 入: 每组测试案例有两行,第一行只有一个整数N,代表着有N间房屋 第二行有N个整数,代表着每间房屋里的金额,金额范围[0, 1000]。 出:

    2024年01月24日
    浏览(78)
  • 【动态规划】矩阵链乘法——算法设计与分析

    对于矩阵 U p × q U_{ptimes q} U p × q ​ 和 V q × r V_{qtimes r} V q × r ​ , Z p × r = U V Z_{ptimes r}=UV Z p × r ​ = U V ,共需计算 p q r pqr pq r 次标量乘法,时间复杂度为 Θ ( p q r ) Theta (pqr) Θ ( pq r ) 矩阵乘法满足结合律,即 ( U V ) W = U ( V W ) (UV)W=U(VW) ( U V ) W = U ( VW ) ,选择不同的结合

    2024年02月03日
    浏览(65)
  • 【动态规划】01背包问题——算法设计与分析

    若超市允许顾客使用一个体积大小为13的背包,选择一件或多件商品带走,则如何选择可以使得收益最高? 商品 价格 体积 啤酒 24 10 汽水 2 3 饼干 9 4 面包 10 5 牛奶 9 4 0-1 Knapsack Problem 输入: quad - n n n 个商品组成集合 O O O ,每个商品有属性价格 p i p_i p i ​ 和体积 v i v_i v

    2024年02月04日
    浏览(79)
  • 【算法设计与分析】动态规划:数塔问题

    提示:头歌 算法作业 实验七 动态规划 第1关:数塔问题 本关任务:编写用动态规划解决数塔问题。 求解过程(自底向上) 决策结果输出过程(自顶向下) 将上述分析求解过程角标记录为 path数组 ,方便顺序输出结果 代码如下(不知题目给出三维数组的a的第三维我用处,去

    2024年02月11日
    浏览(73)
  • 算法设计与分析实验:动态规划与贪心

    目录 一、零钱兑换 1.1 思路一:动态规划 1.2 思路二:贪心 二、安排工作以达到最大效益 2.1 具体思路 2.2 思路呈现 2.3 代码实现 2.4 复杂度分析 2.5 运行结果 三、雇佣k名工人的最低成本 3.1 具体思路 3.2 思路展示 3.3 代码实现 3.4 复杂度分析 3.5 运行结果 结尾语 “生活有意思的

    2024年02月19日
    浏览(75)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包