• 动态规划--背包问题


    题目大意:

    有 $n$ 个物体 第 $i$ 个物体的体积为 $wi$ 价值为 $vi$ 背包容积为 $W$ 求所有挑选方案中价值总和的最大值

    解法1:

     针对每个物品是否放入背包进行搜索

    时间复杂度:$O(2^n)$

    代码:

    #include <bits/stdc++.h>
    using namespace std;
    
    const int maxn = 1e5 + 10;
    int n, W;
    int w[maxn], v[maxn];
    
    int rec(int i, int j) {
        int res;
        if(i == n)
            res = 0;
        else if (j < w[i])
            res = rec(i + 1, j);
        else
            res = max(rec(i + 1, j), rec(i + 1, j - w[i]) + v[i]);
    
        return res;
    }
    
    void solve() {
        printf("%d
    ", rec(0, W));
    }
    
    int main() {
        scanf("%d%d", &n, &W);
        for(int i = 0; i < n; i ++)
            scanf("%d%d", &w[i], &v[i]);
    
        solve();
        return 0;
    }
    

    解法2:

    记忆化搜索,把第一次计算结果存到 $dp$ 数组中,第二次之后如果有同样的 $i, j$ 直接返回

    时间复杂度:$O(n * W)$

    代码:

    #include <bits/stdc++.h>
    using namespace std;
    
    int n, W;
    int w[11111], v[11111];
    int dp[11111][11111];
    
    int rec(int i, int j) {
        if(dp[i][j] >= 0)
            return dp[i][j];
        int res;
        if(i == n)
            res = 0;
        else if(j < w[i])
            res = rec(i + 1, j);
        else
            res = max(rec(i + 1, j), rec(i + 1, j - w[i]) + v[i]);
    
        return dp[i][j] = res;
    }
    
    void solve() {
        memset(dp, -1, sizeof(dp));
        printf("%d
    ", rec(0, W));
    }
    
    int main() {
        scanf("%d%d", &n, &W);
        for(int i = 0; i < n; i ++)
            scanf("%d%d", &w[i], &v[i]);
    
        solve();
        return 0;
    }
    

     解法3:

    dfs

    时间复杂度:$O(2^n)$

    代码:

    #include <bits/stdc++.h>
    using namespace std;
    
    int n, W;
    int w[11111], v[11111];
    
    int dfs(int i, int j, int sum) {
        int res;
        if(i == n)
            res = sum;
        else if(j < w[i])
            res = dfs(i + 1, j, sum);
        else
            res = max(dfs(i + 1, j, sum), dfs(i + 1, j - w[i], sum + v[i]));
    
        return res;
    }
    
    int main() {
        scanf("%d%d", &n, &W);
        for(int i = 0; i < n; i ++)
            scanf("%d%d", &w[i], &v[i]);
    
        int num = dfs(0, W, 0);
        printf("%d
    ", num);
        return 0;
    }
    

    解法4:

    动态规划 不写递归函数,直接用递推式把各项的值计算出来(如果多组输入 $dp$ 需要初始化)

    时间复杂度:$O(n * W)$

    代码1:

    #include <bits/stdc++.h>
    using namespace std;
    
    int n, W;
    int w[11111], v[11111];
    int dp[11111][11111];
    
    void solve() {
        for(int i = n - 1; i >= 0; i --) {
            for(int j = 0; j <= W; j ++) {
                if(j < w[i])
                    dp[i][j] = dp[i + 1][j];
                else
                    dp[i][j] = max(dp[i + 1][j], dp[i + 1][j - w[i]] + v[i]);
            }
        }
        printf("%d
    ", dp[0][W]);
    }
    
    int main() {
        scanf("%d%d", &n, &W);
        for(int i = 0; i < n; i ++)
            scanf("%d%d", &w[i], &v[i]);
    
        solve();
        return 0;
    }

     代码2:

    #include <bits/stdc++.h>
    using namespace std;
    
    int n, W;
    int w[11111], v[11111];
    int dp[11111][11111];
    
    void solve() {
        for(int i = 0; i < n; i ++) {
            for(int j = 0; j <= W; j ++) {
                if(j < w[i])
                    dp[i + 1][j] = dp[i][j];
                else
                    dp[i + 1][j] = max(dp[i][j], dp[i][j - w[i]] + v[i]);
            }
        }
        printf("%d
    ", dp[n][W]);
    }
    
    int main() {
        scanf("%d%d", &n, &W);
        for(int i = 0; i < n; i ++)
            scanf("%d%d", &w[i], &v[i]);
    
        solve();
        return 0;
    }

     代码3:

    #include <bits/stdc++.h>
    using namespace std;
    
    int n, W;
    int w[11111], v[11111];
    int dp[11111][11111];
    
    void solve() {
        for(int i = 0; i < n; i ++) {
            for(int j = 0; j <= W; j ++) {
                dp[i + 1][j] = max(dp[i][j], dp[i + 1][j]);
                if(j + w[i] <= W)
                    dp[i + 1][j + w[i]] = max(dp[i + 1][j + w[i]], dp[i][j] + v[i]);
            }
        }
        printf("%d
    ", dp[n][W]);
    }
    
    int main() {
        scanf("%d%d", &n, &W);
        for(int i = 0; i < n; i ++)
            scanf("%d%d", &w[i], &v[i]);
    
        solve();
        return 0;
    }
    

      

  • 相关阅读:
    渣渣小本求职复习之路每天一博客系列——Java基础(9)
    渣渣小本求职复习之路每天一博客系列——Java基础(8)
    渣渣小本求职复习之路每天一博客系列——Java基础(7)
    渣渣小本求职复习之路每天一博客系列——Java基础(6)
    渣渣小本求职复习之路每天一博客系列——Java基础(5)
    渣渣小本求职复习之路每天一博客系列——Java基础(4)
    渣渣小本求职复习之路每天一博客系列——Java基础(3)
    渣渣小本求职复习之路每天一博客系列——数据结构与常用算法(3)
    redis常用命令
    redis的sets类型
  • 原文地址:https://www.cnblogs.com/zlrrrr/p/9562981.html
Copyright © 2020-2023  润新知