POJ_1742_Coins

描述


http://poj.org/problem?id=1742

给出n中硬币,分别为a[1],a[2],...,a[n],各有c[1],c[2],...,c[n]个,问能组成的面额x(x<=m)有多少.

分析



图文详解:

http://www.hankcs.com/program/cpp/poj-1742-coins.html

用f[j]表示在第i次循环时,用前i-1中硬币组成面额j,第i-1中硬币还剩多少个,如果不能组成面额j,则f[j]=-1.

最后统计f[j]>=0(1<=j<=m)的个数即可.

注意:

1.起始时f[0]=0,表示刚开始可以组成面额0,且之前啥也不剩.

2.之后每次j要从0开始循环,要更新组成面额0(也就是啥都不组成)之后,第i-1种硬币还剩多少个.

3.bind1st表示一元什么什么...也可以写成 " bind2nd(greater_equal<int>(),0) ",这东西貌似在<set>都文件里.

ps.前几天才看过书上的多重部分和问题,这题简直就是模板,然而几乎忘得一干二净了,走马观花真是啥用都没有= =只有真正想明白了才算掌握了一点吧.

#include<cstdio>
#include<cstring>
#include<set>
#include<algorithm>
using namespace std;

const int maxn=105,maxm=100005;
int n,m;
int a[maxn],c[maxn],f[maxm];

void solve()
{
    memset(f,-1,sizeof(f));
    f[0]=0;
    for(int i=1;i<=n;i++)
    {
        for(int j=0;j<=m;j++)
        {
            if(f[j]>=0)
            {
                f[j]=c[i];
            }
            else if(a[i]>j||f[j-a[i]]<=0)
            {
                f[j]=-1;
            }
            else
            {
                f[j]=f[j-a[i]]-1;
            }
        }
    }
    int ans=count_if(f+1,f+m+1,bind1st(less_equal<int>(),0));//统计满足f[j]>=0的个数
    printf("%d\n",ans);
}    

void init()
{
    while(scanf("%d%d",&n,&m)==2&&(n!=0||m!=0))
    {
        for(int i=1;i<=n;i++) scanf("%d",&a[i]);
        for(int i=1;i<=n;i++) scanf("%d",&c[i]);
        solve();
    }
}

int main()
{
#ifndef ONLINE_JUDGE
    freopen("coin.in","r",stdin);
    freopen("coin.out","w",stdout);
#endif
    init();
#ifndef ONLINE_JUDEG
    fclose(stdin);
    fclose(stdout);
    system("coin.out");
#endif
    return 0;
}
时间: 2024-10-07 12:52:49

POJ_1742_Coins的相关文章