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

  • 相关阅读:
    多表头GridView
    Updater Application Block自动更新实施方案[源代码]
    IE和Firefox的Javascript兼容性总结
    JavaScript IE加速
    GridView汇总
    Oracle 中取当前日期的上个月最后天和第一天
    Atitit,通过pid获取进程文件路径 java php  c#.net版本大总结
    Atitit. 数据库catalog与schema的设计区别以及在实际中使用 获取数据库所有库表 java jdbc php  c#.Net
    Atitit. 数据约束 校验 原理理论与 架构设计 理念模式java php c#.net js javascript mysql oracle
    Atitit.一些公司的开源项目 重大知名开源项目attilax总结
  • 原文地址:https://www.cnblogs.com/sunjianzhao/p/11423164.html
Copyright © 2011-2022 走看看