描述
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