• 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
  • 相关阅读:
    linux杀死僵尸进程
    通过dd命令显示硬盘的读写性能
    linux 压缩与解压缩
    linux云主机cpu一直很高降不下来,系统日志报nf_conntrack: table full, dropping packet.
    vsftp配置文件详解
    linux中ping带时间及打印内容到文件
    atop工具检测linux硬件异常
    windows连接服务端的域名正常,linux却不通,(针对于负载均衡后端节点设置)
    有你的地方就是天堂
    Java 异常 —— java.io.InvalidClassException: javax.xml.namespace.QName; local class incompatible
  • 原文地址:https://www.cnblogs.com/zhaopAC/p/5046215.html
Copyright © 2020-2023  润新知