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

    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


    做这个题时,第一次这么写的:
    #include<iostream>
    #include<cstdio>
    using namespace std;
    bool dp[100][100001];
    int n,m,a[100],su[100];
    int main(){
    while(cin>>n>>m){
    if(n==0&&m==0) return 0;
    for(int i=0;i<n;i++)
    for(int j=1;j<=m;j++)
    dp[i][j]=false;
    for(int i=0;i<n;i++)
    scanf("%d",&a[i]),dp[i][0]=true; //dp[i][j]为真,表示j元可以凑出来 ,a[i]硬币的面额
    for(int i=0;i<n;i++)
    scanf("%d",&su[i]); //su[i]表示面额为a[i]的硬币的数量
    for(int i=1;i<=su[0]&&a[0]*i<=m;i++) //注意a[0]*i<=m,or就会出现runtime error
    dp[0][a[0]*i]=true;
    for(int i=1;i<n;i++){
    for(int j=1;j<=m;j++){
    for(int k=1;k<=su[i];k++){
    if(j-k*a[i]>=0&&dp[i-1][j-k*a[i]]) dp[i][j]=true;
    else dp[i][j]=dp[i-1][j];
    }
    }
    }
    int s=0;
    for(int i=1;i<=m;i++){
    if(dp[n-1][i]) /*printf("%d ",i),*/s++;
    }
    printf("%d ",s);
    }
    }
    这么写的话会超时,虽然这个dp好理解,但是这个dp的复杂度为O(m(su[i]的和))
    现在附上第二次AC代码:
    #include<iostream>
    #include<cstdio>
    #include<cstring>
    using namespace std;
    int dp[2][100005];
    int main(){
    int n,m,va[102],su[102];
    while(cin>>n>>m){
    if(n==0&&m==0) return 0;
    memset(dp,-1,sizeof(dp));
    for(int i=0;i<n;i++)
    scanf("%d",&va[i]); //硬币的面额
    for(int i=0;i<n;i++)
    scanf("%d",&su[i]); //面额为va[i]的硬币的数量
    for(int i=0;i<=su[0]&&va[0]*i<=m;i++)
    dp[0][va[0]*i]=su[0]-i;
    for(int i=1;i<n;i++){
    for(int j=0;j<=m;j++){
    if(dp[(i-1)%2][j]>=0) dp[i%2][j]=su[i];
    else if(j<va[i]||dp[i%2][j-va[i]]<=0) dp[i%2][j]=-1;
    else dp[i%2][j]=dp[i%2][j-va[i]]-1;
    }
    }
    int s=0;
    for(int i=1;i<=m;i++)
    if(dp[(n-1)%2][i]>=0) /*printf("%d ",i),*/s++;
    printf("%d ",s);
    }
    }
    这个复杂度为O(nm),
    dp[i][j]表示前i+1中硬币加和得到j元钱时,第i+1种硬币剩余的数量。


    作者:孙建钊
    出处:http://www.cnblogs.com/sunjianzhao/
    本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则保留追究法律责任的权利。

  • 相关阅读:
    Halcon一日一练:图像分割之基本概念
    Halcon一日一练:创建AOI
    Halcon一日一练:获取图像属性
    Halcon一日一练:创建三通道图像
    Halcon一日一练:Halcon异常判断方法
    Java基础_类的加载机制和反射
    Java基础_死锁、线程组、定时器Timer
    Java基础_通过模拟售票情景解决线程不安全问题
    Java基础_线程的使用及创建线程的三种方法
    HTML/HTML5 知识点思维导图
  • 原文地址:https://www.cnblogs.com/sunjianzhao/p/11423164.html
Copyright © 2011-2022 走看看