poj 1276

一道DP的题目,还是一道多重背包的题目,第一次接触。

题意:有现今cash,和n种钱币,每种钱币有ni个,价值为di,求各种钱币组成的不超过cash的最大钱数

思路:可以转换为0/1背包和完全背包来做。

  1 Memory: 648K		Time: 16MS
  2 Language: C++		Result: Accepted
  3 #include <stdio.h>
  4 #include <iostream>
  5 #include <string.h>
  6 
  7 int cash,n;
  8 
  9 int num[100005],price[100005];
 10 
 11 bool us[100005];
 12 int user[100005];
 13 
 14 void calc()
 15 {
 16     memset(us,false,sizeof(us));
 17     us[0]=true;
 18     for(int i=0;i<n;i++)
 19     {
 20         memset(user,0,sizeof(user));
 21         for(int j=price[i];j<=cash;j++)
 22             if(us[j-price[i]]&&!us[j]&&user[j-price[i]]<num[i])   //这是这个程序的重点,为什么j++,而不是j成倍的增加price倍,其实,这通过us[j-price[i]]和!us[j]就限制了,它只可以增加price倍,当增加的不是price的倍数时,us[j-price[i]]是假的,当j为2倍时,由于之前us[j]也就是us[price]被赋值为了ture,所以这个if语句成立。以此类推
 23         {
 24             us[j]=true;
 25             user[j]=user[j-price[i]]+1;
 26         }
 27     }
 28 }
 29 
 30 int main()
 31 {
 32     while(scanf("%d%d",&cash,&n)!=EOF)
 33     {
 34         for(int i=0;i<n;i++)
 35             scanf("%d%d",&num[i],&price[i]);
 36         calc();
 37         for(int i=cash;i>=0;i--)
 38             if(us[i])
 39             {
 40                 printf("%d
",i);
 41                 break;
 42             }
 43     }
 44     return 0;
 45 }
原文地址:https://www.cnblogs.com/Tree-dream/p/5589546.html