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

      

  • 相关阅读:
    LeetCode 130. 被围绕的区域 (DFS)
    LeetCode 200. 岛屿数量 (BFS)
    LeetCode 200. 岛屿数量 (DFS)
    Win10下Anaconda命令行相关操作
    LeetCode 53. 最大子序和
    从尾到头打印链表
    字符串逆序
    交换俩字符串
    LeetCode 147. 对链表进行插入排序
    LeetCode 面试题 02.08. 环路检测
  • 原文地址:https://www.cnblogs.com/wenruo/p/4506652.html
Copyright © 2011-2022 走看看