• UVa 624 CD && joj 1387 CD 背包问题 yongmou


      题意很简单:n个东西,装入容量为c的背包,怎么使装的东西重量和最大。其实,就是价值等于重量的0/1背包问题。

      UVa 上规模比较小n最大值是20, 用DP把最大容量设置大点就可以AC,但是JOJ上n最大值是100,又没有告诉容量最大有多大,用DP一用就Runtime Error,在设置大点就Memory Limit Exceeded,只好用DFS搜索了。

      DFS搜索的剪枝还挺有技巧性的,其实,一般的讲分支限界法的算法书上都有。具体的剪枝,我都写在代码的注释里了。

    DP代码:


    #include
    <fstream>
    #include
    <iostream>
    using namespace std;

    const int MAX = 104;

    int m[MAX][MAX*MAX];// m[i][j]是背包容量为j, 可选择物品为i, i+1, ... , n时, 01背包问题的最优值
    int w[MAX]; //重量=价值, 索引从1开始
    int x[MAX]; //解向量
    int c; //容量
    int n;

    int max(int a, int b) {
    return (a > b ? a : b);
    }

    void knapsack() {
    int i, j;
    for (i = 0; i <= c; ++i)
    m[
    0][i] = 0;
    for (i = 0; i <= n; ++i)
    m[i][
    0] = 0;
    for (i = 1; i <= n; ++i)
    for (j = 1; j <= c; ++j) {
    if (j < w[i])
    m[i][j]
    = m[i - 1][j];
    else
    m[i][j]
    = max(m[i - 1][j], m[i - 1][j - w[i]] + w[i]);
    }
    }

    void backtrace() {
    int max = c;
    for (int i = n; i >= 1; --i) {
    if(m[i][max] == m[i-1][max])
    x[i]
    = 0;
    else{
    x[i]
    = 1;
    max
    -= w[i];
    }
    }
    }
    int main() {
    // ifstream cin("in");
    while (cin >> c) {
    cin
    >> n;
    for (int i = 1; i <= n; i++) {
    cin
    >> w[i];
    }
    knapsack();
    backtrace();
    for(int i=1; i<=n; ++i){
    if(x[i] == 1)
    cout
    <<w[i]<<" ";
    }
    cout
    << "sum:" << m[n][c] << endl;
    }
    return 0;
    }

    DFS搜索代码:

    #include<cstdio>
    #include
    <algorithm>
    using namespace std;

    const int MAX = 100;
    int w[MAX]; //重量=价值, 索引从1开始
    int s[MAX]; //从前向后的累积
    int mc;
    int c; //容量
    int n; //磁道数量

    void backtrack(int k, int cur) {
    if (mc == c)
    return; //已经达到最大容量
    if (k < 0)
    return;
    if (cur + s[k] <= mc)
    return; //把前面的都加上还没有现在的大
    if (cur + w[0] > c)
    return; //即使加上最小的也超了

    int t = cur + w[k];
    if (t <= c && t > mc)
    mc
    = t;
    if (t <= c)
    backtrack(k
    - 1, t);
    backtrack(k
    - 1, cur);
    }

    int main() {
    // freopen("in", "r", stdin);
    while (scanf("%d %d", &c, &n) != EOF) {
    for (int i = 0; i < n; i++)
    scanf(
    "%d", &w[i]);

    sort(w, w
    + n); //排序,使小的放在前面
    s[0] = w[0];
    for (int i = 1; i < n; ++i)
    s[i]
    = s[i - 1] + w[i];
    mc
    = 0;
    backtrack(n
    - 1, 0);
    printf(
    "sum:%d\n", mc);
    }
    return 0;
    }
  • 相关阅读:
    1.2顺序表
    1.1数据结构
    Java 造假数据
    Python造假数据,用这个库
    真香 用这七大Python效率工具
    mybatis 详情
    MySQL 的 INSERT ··· ON DUPLICATE KEY UPDATE
    mysql之case when then 经典用法
    SELECT NOW(),CURDATE(),CURTIME()
    MySQL CONCAT_WS 函数
  • 原文地址:https://www.cnblogs.com/liyongmou/p/1774039.html
Copyright © 2020-2023  润新知