动态规划

动态规划

(参考灯神视频

1.fibnacci(热身)

fibnacci问题如果我们直接递归求解,则花费时间复杂度为O(n^2),但是我们只要进行保存状态,则可以转化为O(n)

// O(n^2)
int fibnacci_recrusion(int n) {
    if(n == 1 || n == 2) return 1;
    return fibnacci_recrusion(n - 1) + fibnacci_recrusion(n - 2);
}
// O(n)
int fibnacci_loop(int n) {
    int arr[99999];
    arr[1] = arr[2] = 1;
    for(int i = 3; i <= n; i++) 
        arr[i] = arr[i - 1] + arr[i - 2];
    return arr[n];
}

这就是重叠子问题

2.任务

每个任务占用以下时间片,每个任务可以赚红字的钱,我们如何利用dp进行求解

思路,我们对每个任务都有选和不选两种。然后进行递归求解,v代表

\[Opt(i) = max(v(i) + opt(i - 1), v(i-1)) \]

我们还需要一个prev最优解

i           1  2  3  4  5  6  7  8  (选中)
prev(i)     0  0  0  1  0  2  3  5  (前面紧跟的)
opt(i)      5  5  8  9  9  9  10 13 

3.选数字

从4 1 1 9 1,选出不相邻的两个,并且和最大,我们也是同样的思路,找prev,和优化的数组,进行循环

#include <iostream>
using namespace std;
int arr[] = { 4, 1, 1, 9, 1 };
int _prev[] = { 0, 0, 1, 2, 3, 4 };
int optimize[5];
int main() {
    optimize[0] = optimize[1] = max(arr[0], arr[1]);
    for(int i = 2; i < sizeof(arr); i++)
        optimize[i] = max(optimize[i - 1], arr[i] + optimize[i - 2]);
    printf("%d", optimize[4]);
    return 0;
}

4.特定子列和

从3,34,4,12,2找找有无可能会有n个数相加和为9,如果有,则打印true

思考:我们选,前面的subset则要是减去这个数,否则是直接子列

#include <iostream>
using namespace std;
int arr[] = { 3, 34, 4, 12, 2 };
bool subset(int i, int sum) {
    if(sum == 0) return true;
    else if(i == 0) return arr[0] == sum;
    else if(arr[i] > sum) return subset(i - 1, sum);
    else return subset(i - 1, sum - arr[i]) || subset(i - 1, sum);
}
int main() {
    printf("%d", subset(4, 4));
    return 0;
}
// 我们也可以转换成循环
posted @ 2020-04-24 14:19  SteveYu  阅读(169)  评论(0编辑  收藏  举报