zoukankan      html  css  js  c++  java
  • 动态规划--背包问题

    题目大意:

    有 $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;
    }
    

      

  • 相关阅读:
    js的单元测试
    如何嵌入HTML 页面
    使用JQuery时间比较
    @page指令ValidateRequest的作用
    时间的正则表达式(比较简单)
    [置顶] Android代码 监控手机电池的状态
    [置顶] Android代码传感器光传感
    [置顶] Android问题ViewPager实现左右两个屏幕的切换
    [置顶] Android代码传感器测试手机支持那几种传感
    [置顶] Android代码检测手机耳机插拔
  • 原文地址:https://www.cnblogs.com/zlrrrr/p/9562981.html
Copyright © 2011-2022 走看看