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/
    本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则保留追究法律责任的权利。

  • 相关阅读:
    所有抽样单元都有相等的被选取机会 ,说法错误
    银行存款余额表由谁编制的
    资本公积——资本溢价与资本公积——其他资本公积
    货币单元抽祥
    企业安全生产费用账务的处理
    Tableau代写制作地图可视化和树形图、条形图
    Tableau 代写数据可视化:探索性图形分析新生儿死亡率数据
    R、Python代写、Open Refine采集pdf数据,清理数据和格式化数据
    使用GIS编程代写制作静态地图和处理地理数据
    用R语言编程代写制作交互式图表和地图
  • 原文地址:https://www.cnblogs.com/sunjianzhao/p/11423164.html
Copyright © 2011-2022 走看看