poj1276——cash machine

来源:互联网 发布:算法心得 epub 编辑:程序博客网 时间:2024/06/06 19:52

前情提要:

<0-1背包>n个物品,背包容量为C,每个物品容积为w[i],每个物品价值为v[i],求将哪些物品放入背包不超过背包容积,且价值最大

              状态为dp[i][j],表示考虑选择第i...到n个物品,容量为j时的最大价值              

              转移方程为dp[i][j]=max{dp[i+1][j],dp[i+1][j-w[i]]+v[i]}(当w[i]<=j时)

                                        =dp[i+1][j](当w[i]>j时)

              结果为dp[1][C]

<完全背包>区别在于每个物品的个数无上限,也就是说不是放与不放两种情况,而是放0,1,2...多少个

                转移方程为dp[i][j]=max{dp[i+1][j],dp[i+1][j-k*w[i]]+k*v[i]},0<=k*w[i]<=j

                                          =dp[i+1][j],k*w[i]>j

<多重背包问题>区别在于每个物品的个数为指定的n[i]个,也就是第i个物品数量为n[i]

                      转移方程为dp[i][j]=max{dp[i+1][j],dp[i+1][j-k*w[i]]+k*v[i]},0<=k<=n[i],0<=k*w[i]<=j

                                          =dp[i+1][j],k*w[i]>j

题目大意:要取定额为cash的钱,有n中面额的钱,面额为b[i]的钱有a[i]张,求能提供的最接近并不超过要取金额的数值

输入:cash N  n1  D1  n2  D2...

          735  3  4  125  6  5  3  350

输出:所求数值

分析:典型的多重背包问题,n种纸币(物品),每种面额(重量)为b[i]的纸币(物品)有a[i]张(个)。在这个问题中,单个物品的价值等于它的重量(面值)。

以下代码摘自http://www.bubuko.com/infodetail-634095.html

1 #include <cstdio> 2 #include <cstring> 3  4 const int maxn = 12;//纸币种类数量0<=n<=10 5 const int maxp = 100000 + 10;//0<=cash<=100000 6  7 bool vis[maxp];//是否到达总面值i 8 int used[maxp];//到达总面值i时,该种纸币所用的数量 9 int a[maxn], b[maxn];//每种纸币的数量以及面值10 11 int cash, n;12 13 int main()14 {15     //freopen("in.txt", "r", stdin);16 17     while(scanf("%d", &cash) == 1)18     {19         scanf("%d", &n);20         for(int i = 0; i < n; ++i) scanf("%d%d", &a[i], &b[i]);21 22         memset(vis, false, sizeof(vis));23         vis[0] = true;24         for(int i = 0; i < n; ++i)//前i种纸币可选时的状态25         {26             memset(used, 0, sizeof(used));27             for(int j = b[i]; j <= cash; ++j)//对于第i种纸币,b[i]~cash这些状态都可能发生28                 if(vis[j-b[i]] && !vis[j] && used[j-b[i]] < a[i])//只有当j-b[i]已经达到过时才能进行。要取某种面额,需确保这次操作之前所取该面额                               的次数不超过a[i]29                 { vis[j] = true; used[j] = used[j-b[i]] + 1; }30         }31 32         for(int i = cash; i >= 0; --i) if(vis[i]) { printf("%d\n", i); break; }33     }34 35     return 0;36 }