zoukankan      html  css  js  c++  java
  • POJ1742Coins(多重背包)

    Coins
    Time Limit: 3000MS   Memory Limit: 30000K
    Total Submissions: 32309   Accepted: 10986

    Description

    People in Silverland use coins.They have coins of value A1,A2,A3...An Silverland dollar.One day Tony opened his money-box and found there were some coins.He decided to buy a very nice watch in a nearby shop. He wanted to pay the exact price(without change) and he known the price would not more than m.But he didn't know the exact price of the watch. 
    You are to write a program which reads n,m,A1,A2,A3...An and C1,C2,C3...Cn corresponding to the number of Tony's coins of value A1,A2,A3...An then calculate how many prices(form 1 to m) Tony can pay use these coins. 

    Input

    The input contains several test cases. The first line of each test case contains two integers n(1<=n<=100),m(m<=100000).The second line contains 2n integers, denoting A1,A2,A3...An,C1,C2,C3...Cn (1<=Ai<=100000,1<=Ci<=1000). The last test case is followed by two zeros.

    Output

    For each test case output the answer on a single line.

    Sample Input

    3 10
    1 2 4 2 1 1
    2 5
    1 4 2 1
    0 0
    

    Sample Output

    8
    4

    题意:给出3种硬币的面额和数量,能拼成不大于m的多少种;
    多重背包可解,因为只要求行或不行就可以了,所以就两种状态在01和完全背包的时候没必要求可行解,只要确定行或不行就ok了,所以直接与dp[j - a[i]] 或运算,
    注意的是,位运算真的好快,把dp设成int,用关系运算||,是超时的,改成位运算的|直接3000ms卡过;
    改成bool型直接2204ms;
     1 #include <iostream>
     2 #include <cstring>
     3 #include <algorithm>
     4 #include <cstdio>
     5 using namespace std;
     6 const int MAX = 100000 + 10;
     7 bool dp[MAX];
     8 int a[100 + 10],c[100 + 10];
     9 int n,m;
    10 void ZeroOnePage(int cost)
    11 {
    12     for(int i = m; i >= cost; i--)
    13     {
    14         dp[i] |= dp[i - cost];
    15     }
    16 }
    17 void CompletePage(int cost, int mount)
    18 {
    19     for(int i = cost; i <= m; i++)
    20         dp[i] |= dp[i - cost];
    21 }
    22 void MultiplePage(int cost, int mount)
    23 {
    24     if(cost * mount >= m)
    25     {
    26         CompletePage(cost, mount);
    27         return ;
    28     }
    29     int k = 1;
    30     while(k < mount)
    31     {
    32         ZeroOnePage(k * cost);
    33         mount -= k;
    34         k <<= 1;
    35     }
    36     if(mount > 0)
    37         ZeroOnePage(mount * cost);
    38     return ;
    39 }
    40 int main()
    41 {
    42     while(scanf("%d%d", &n, &m) != EOF)
    43     {
    44         if(n == 0 && m == 0)
    45             break;
    46         for(int i = 1; i <= n; i++)
    47             scanf("%d", &a[i]);
    48         for(int i = 1; i <= n; i++)
    49             scanf("%d", &c[i]);
    50         memset(dp, 0, sizeof(dp));
    51         dp[0] = 1;
    52         for(int i = 1; i <= n; i++)
    53             if(c[i])
    54                 MultiplePage(a[i], c[i]);
    55         int sum = 0;
    56         for(int i = 1; i <= m; i++)
    57             if(dp[i])
    58                 sum++;
    59         printf("%d
    ",sum);
    60     }
    61 
    62     return 0;
    63 }
    多重背包好理解
    #include <iostream>
    #include <cstring>
    #include <algorithm>
    #include <cstdio>
    using namespace std;
    const int MAX = 100000 + 10;
    bool dp[MAX];
    int a[100 + 10],c[100 + 10];
    int n,m;
    void ZeroOnePage(int cost)
    {
        for(int i = m; i >= cost; i--)
        {
            dp[i] |= dp[i - cost];
        }
    }
    void CompletePage(int cost, int mount)
    {
        for(int i = cost; i <= m; i++)
            dp[i] |= dp[i - cost];
    }
    void MultiplePage(int cost, int mount)
    {
        if(cost * mount >= m)
        {
            CompletePage(cost, mount);
            return ;
        }
        int k = 1;
        while(k < mount)
        {
            ZeroOnePage(k * cost);
            mount -= k;
            k <<= 1;
        }
        //这里是还剩下的mount
        if(mount > 0)
            ZeroOnePage(mount * cost);
        return ;
    }
    int main()
    {
        while(scanf("%d%d", &n, &m) != EOF)
        {
            if(n == 0 && m == 0)
                break;
            for(int i = 1; i <= n; i++)
                scanf("%d", &a[i]);
            for(int i = 1; i <= n; i++)
                scanf("%d", &c[i]);
            memset(dp, 0, sizeof(dp));
            dp[0] = 1;
            for(int i = 1; i <= n; i++)
                if(c[i])
                    MultiplePage(a[i], c[i]);
            int sum = 0;
            for(int i = 1; i <= m; i++)
                if(dp[i])
                    sum++;
            printf("%d
    ",sum);
        }
    
        return 0;
    }
    
    多重背包好理解
    这种解法看不懂
     1 #include <iostream>
     2 #include <cstring>
     3 #include <algorithm>
     4 #include <cstdio>
     5 using namespace std;
     6 const int MAX = 100000 + 10;
     7 int dp[MAX],used[MAX],a[100 + 10],c[100 + 10];
     8 int n,m;
     9 int main()
    10 {
    11     while(scanf("%d%d", &n, &m) != EOF)
    12     {
    13         if(n == 0 && m == 0)
    14             break;
    15         for(int i = 1; i <= n; i++)
    16             scanf("%d", &a[i]);
    17         for(int i = 1; i <= n; i++)
    18             scanf("%d", &c[i]);
    19         memset(dp, 0, sizeof(dp));
    20         dp[0] = 1;
    21         int sum = 0;
    22         for(int i = 1; i <= n; i++)
    23         {
    24             memset(used, 0, sizeof(used));
    25             for(int j = a[i]; j <= m; j++)
    26             {
    27                 if(dp[j] == 0 && dp[j - a[i]] && used[j - a[i]] < c[i])
    28                 {
    29                     sum++;
    30                     dp[j] = 1;
    31                     used[j] = used[j - a[i]] + 1;
    32                 }
    33             }
    34         }
    35         printf("%d
    ",sum);
    36     }
    37 
    38     return 0;
    39 }
    View Code
  • 相关阅读:
    c#——树的深度,广度优先遍历与迭代器(IEnumerable<T>)的结合使用
    弱网下移动端网络连接处理策略
    弱网络环境下最优调度和优化传输层协议方案
    Wpf ToolTip 绑订
    minio配置
    使用本机映像优化 NET 桌面应用
    Linux内核内存管理:系统内存布局-内核空间和用户空间
    mysql 的 limit 与sql server 的 top n
    win 10 遇到某文件一直在占用导致无法关闭,或者去任务管理器找不到服务怎么办?具体解决
    sql server
  • 原文地址:https://www.cnblogs.com/zhaopAC/p/5046215.html
Copyright © 2011-2022 走看看