zoukankan      html  css  js  c++  java
  • hdu 01背包汇总(1171+2546+1864+2955。。。

    1171

    题意比较简单,这道题比较特别的地方是01背包中,每个物体有一个价值有一个重量,比较价值最大,重量受限,这道题是价值受限情况下最大,也就值把01背包中的重量也改成价值。

    //Problem : 1171 ( Big Event in HDU )     Judge Status : Accepted
    
    #include <cstdio>
    #include <cstring>
    #include <algorithm>
    #include <iostream>
    
    using namespace std;
    
    int v[6000], dp[5000 * 50 + 10];
    
    
    int main() {
        //freopen("in.txt", "r", stdin);
        int n;
        int sum;
        while (scanf("%d", &n) != EOF && n >= 0) {
            memset(dp, 0, sizeof(dp));
            int a, b;
            sum = 0;
            int idx = 0;
            for (int i = 1; i <= n; i++) {
                scanf("%d%d", &a, &b);
                sum += a * b;
                for (int j = 0; j < b; j++) {
                    v[++idx] = a;
                }
            }
            for (int i = 1; i <= idx; i++)
                for (int j = sum / 2; j >= v[i]; j--)
                    dp[j] = max(dp[j], dp[j - v[i]] + v[i]);
            printf("%d %d
    ", sum - dp[sum / 2], dp[sum / 2]);
        }
        return 0;
    }
    

    2546

    和上面一样,没有重量,只有价值。

    如果卡上不足5元,输出原值。如果大于5元,就在m-5范围内花最多的钱(留下最贵的菜),然后用剩下的钱减去最贵的菜。

    代码

    //Problem : 2546 ( 饭卡 )     Judge Status : Accepted
    #include <iostream>
    #include <algorithm>
    using namespace std;
    
    int v[1005];
    int dp[1005];
    
    int main()
    {
        int n, m;
        while (cin >> n && n) {
            memset(dp, 0, sizeof(dp)); //又忘记初始化然后wa了一发。。。
            for (int i = 1; i <= n; ++i) {
                cin >> v[i];
            }
            cin >> m;
            if (m < 5) {
                printf("%d
    ", m);
                continue;
            }
            sort(v + 1, v + n + 1);
            for (int i = 1; i < n; ++i) {
                for (int j = m - 5; j >= v[i]; j--)
                    dp[j] = max(dp[j], dp[j - v[i]] + v[i]);
            }
            printf("%d
    ", m - dp[m - 5] - v[n]);
        }
    
        return 0;
    }
    

    2602

    水题,不写了。基本01背包。

    1864

    题意很简单,做法也很简单,全部*100变成整数然后01背包。

    一处(int)(q*100)不小心写成了(int)q*100调试了好久才找到,蠢蠢蠢= =

    //Problem : 1864 ( 最大报销额 )     Judge Status : Accepted
    
    /**<  hdu 1864 */
    #include <iostream>
    #include <cstdio>
    #include <algorithm>
    
    using namespace std;
    
    double pri[35];     //合法发票的价格
    int pric[35];
    int dp[35 * 1000 * 100];
    
    int main()
    {
        double q;
        int n, m;
        double pri_a, pri_b, pri_c;
        while (scanf("%lf%d", &q, &n) != EOF && n) {
            int idx = 0;
            for (int i = 0; i < n; ++i) {
                cin >> m;
                pri_a = pri_b = pri_c = 0;
                char ch;
                double price;
                int ok = 1;
                for (int j = 0; j < m; ++j) {
                    scanf(" %c:%lf", &ch, &price);
                    switch(ch) {
                    case 'A' :
                        pri_a += price;
                        break;
                    case 'B' :
                        pri_b += price;
                        break;
                    case 'C' :
                        pri_c += price;
                        break;
                    default: ok = 0;
                    }
                }
                double sum = pri_a + pri_b + pri_c;
                //printf("a=%f,b=%f,c=%f,sum=%f
    ", pri_a, pri_b, pri_c, sum);
                if (!(pri_a > 600 || pri_b > 600 || pri_c > 600 || sum > 1000) && ok) pri[++idx] = sum;
            }   //end for 求出pri[]
    
            for (int i = 1; i <= idx; i++) {
                pric[i] = (int)(pri[i] * 100);
            }
    
            memset(dp, 0, sizeof(dp));
            for (int i = 1; i <= idx; ++i) {
                for (int j = (int)(q * 100); j >= pric[i]; --j) {
                        dp[j] = max( dp[j], dp[j - pric[i]] + pric[i]);
                }
            }
            printf("%.2f
    ", dp[(int)(q * 100)] / 100.00);
        }
        return 0;
    }
    

    这题也可以换一种方法做,用张数当背包。

    我们平时的背包都是质量,当数据过大,或像这个一样是实数,可以转换思维,用价值当背包等。

    //Problem : 1864 ( 最大报销额 )     Judge Status : Accepted
    
    #include <iostream>
    #include <cstdio>
    #include <algorithm>
    
    using namespace std;
    
    double pri[35];
    double dp[35];
    
    int main()
    {
        double q;
        int n, m;
        double pri_a, pri_b, pri_c;
        while (scanf("%lf%d", &q, &n) != EOF && n) {
            int idx = 0;
            for (int i = 0; i < n; ++i) {
                cin >> m;
                pri_a = pri_b = pri_c = 0;
                char ch;
                double price;
                int ok = 1;
                for (int j = 0; j < m; ++j) {
                    scanf(" %c:%lf", &ch, &price);
                    switch(ch) {
                    case 'A' :
                        pri_a += price;
                        break;
                    case 'B' :
                        pri_b += price;
                        break;
                    case 'C' :
                        pri_c += price;
                        break;
                    default: ok = 0;
                    }
                }
                double sum = pri_a + pri_b + pri_c;
                //printf("a=%f,b=%f,c=%f,sum=%f
    ", pri_a, pri_b, pri_c, sum);
                if (!(pri_a > 600 || pri_b > 600 || pri_c > 600 || sum > 1000) && ok) pri[++idx] = sum;
            }   //end for 求出pri[]
    
    
            for (int i = 0; i <= idx; i++) {
                dp[i] = 0.0;
            }
    
            for (int i = 1; i <= idx; ++i) {
                for (int j = idx; j >= 1; --j) {
                    if (dp[j - 1] + pri[i] <= q)
                        dp[j] = max(dp[j], dp[j - 1] + pri[i]);
                }
            }
            double ans = 0;
            for (int i = 1; i <= idx; ++i)
                if (ans < dp[i]) ans = dp[i];
            printf("%.2f
    ", ans);
        }
        return 0;
    }
    

    2955

    又是一道不是整数的题,可以看出这道题不能像上一道那样简答的通过x100完成,因为精度不够。

    可以把概率当背包,这题还有一处不同就是不是加,概率是乘

    //Problem : 2955 ( Robberies )     Judge Status : Accepted
    
    #include <iostream>
    #include <cstdio>
    #include <algorithm>
    #include <cstring>
    using namespace std;
    
    double P[105];  //每一家银行不被抓的概率
    int M[105];     //每一家银行偷到的钱...
    double dp[10005];
    
    int main()
    {
        int t;
        cin >> t;
        while (t--) {
            int n;
            int sum = 0;
            double p;
            cin >> p >> n;
            for (int i = 1; i <= n; ++i) {
                cin >> M[i] >> P[i];
                P[i] = 1 - P[i];
                sum += M[i];
            }
            memset(dp, 0, sizeof(dp));//又特么忘了这句wa一发。。。
            dp[0] = 1;  //不偷时不被抓概率是1
            for (int i = 1; i <= n; ++i) {
                for (int j = sum; j >= M[i]; --j) {
                    dp[j] = max(dp[j], dp[j - M[i]] * P[i]); //不被抓的概率最大
                }
            }
            for (int i = sum; i >= 0; --i)
                if (dp[i] > 1 - p) {
                    printf("%d
    ", i);
                    break;
                }
        }
        return 0;
    }
    

      

  • 相关阅读:
    Coursera机器学习week11 单元测试
    关于 TypeReference 的解释
    getModifiers 方法解释。
    instanceof isInstance isAssignableFrom 比较
    elasticsearch 基础 语法总结
    kibana 启动 关闭 和进程查找
    MD5 SHA1 SHA256 SHA512 SHA1WithRSA 的区别
    spring boot 项目 热启动
    java zip 压缩文件
    Packet for query is too large (1660 > 1024). You can change this value on the server by setting the max_allowed_packet' variable.
  • 原文地址:https://www.cnblogs.com/wenruo/p/4506652.html
Copyright © 2011-2022 走看看