zoukankan      html  css  js  c++  java
  • Coins [POJ1742] [DP]

     
    Description
    给出硬币面额及每种硬币的个数,求从1到m能凑出面额的个数。
    Input
    多组数据,每组数据前两个数字为n,m。n表示硬币种类数,m为最大面额,之后前n个数为每种硬币的面额,后n个数为相应每种硬币的个数。 (n<=100,m<=100000,面额<=100000,每种个数<=1000)
    Output
    如题
    Sample Input
    3 10
    1 2 4 2 1 1
    2 5
    1 4 2 1
    0 0
    
    Sample Output
    8
    4
    Solution
    这是典型的多重部分和问题
    首先我们很容易想到的就是记录dp[i][j]表示用前i中数字能否加成j
    那么状态转移方程就是dp[i][j]|=dp[i-1][j-k*a[i]]
    我们可以发现时间复杂度是O(m*∑面额),这并不优秀!
    因为dp时求bool值一般不会很高效,我们换种思路
    记dp[i][j]为,用前i个数加成j,i种最多剩下多少个
    那我们就有以下方程:
    if(dp[i-1][j]>=0)           dp[i][j]=num[i];
    else if(dp[i-1][j-val[i]]<=0||val[i]>j)   dp[i][j]=-1;
    else                dp[i][j]=dp[i][j-val[i]]-1;
    最后统计dp[n][i]>=0的个数
    Code
     1 #include<set>
     2 #include<map>
     3 #include<queue>
     4 #include<stack>
     5 #include<cmath>
     6 #include<cstdio>
     7 #include<cstring>
     8 #include<iostream>
     9 #include<algorithm>
    10 #define RG register int
    11 #define rep(i,a,b)    for(RG i=a;i<=b;++i)
    12 #define per(i,a,b)    for(RG i=a;i>=b;--i)
    13 #define ll long long
    14 #define inf (1<<29)
    15 #define maxn 105
    16 #define maxm 100005
    17 using namespace std;
    18 int n,m;
    19 int val[maxn],num[maxn];
    20 int dp[maxm];
    21 inline int read()
    22 {
    23     int x=0,f=1;char c=getchar();
    24     while(c<'0'||c>'9'){if(c=='-')f=-1;c=getchar();}
    25     while(c>='0'&&c<='9'){x=x*10+c-'0';c=getchar();}
    26     return x*f;
    27 }
    28 
    29 void DP()
    30 {
    31     memset(dp,-1,sizeof(dp));
    32     dp[0]=0;
    33     rep(i,1,n)
    34         rep(j,0,m)
    35         {
    36             if(dp[j]>=0)                        dp[j]=num[i];
    37             else if(val[i]>j||dp[j-val[i]]<=0)    dp[j]=-1;
    38             else                                dp[j]=dp[j-val[i]]-1;
    39         }
    40     int ans=0;
    41     rep(i,1,m)
    42         if(dp[i]>=0)    ans++;
    43     printf("%d
    ",ans);    
    44 }
    45 
    46 int main()
    47 {
    48     while(1)
    49     {
    50         n=read(),m=read();
    51         if(!n&&!m)    return 0;
    52         rep(i,1,n)     val[i]=read();
    53         rep(i,1,n)    num[i]=read();
    54         DP();
    55     }
    56     return 0;
    57 }
    View Code
  • 相关阅读:
    学习使用apt(三)
    2005 男人感悟100(转自MOP)
    学习使用apt
    学习使用apt(四)
    编译glib1.2.20r5出错./libtool: line 297
    poj1004的java实现
    猜算式
    基于爬山算法求解TSP问题(JAVA)
    mysql数据库的简单语句的介绍(1)
    NYOJ42 一笔画问题
  • 原文地址:https://www.cnblogs.com/ibilllee/p/9211093.html
Copyright © 2011-2022 走看看