POJ 1276 Cash Machine(多重背包问题)
2015-06-21 17:51
435 查看
Description
有各种不同面值的货币,每种面值的货币有不同的数量,请找出利用这些货币可以凑成的最接近且小于等于给定的数字cash的金额
Input
多组用例,以文件尾结束输入。
每组用例以cash N n1 D1 n2 D2 ..nN DN形式输入
(0<=cash<=100000,0<=N<=10,0<=ni<=1000,1<=nk<=1000)
cash为货币和上限,N为货币种类,ni和Di分别为每种货币的面额和数量
Output
对于每组用例,输出利用给出货币可以凑成的最接近的小于等于cash的金额
Sample Input
735 3 4 125 6 5 3 350
633 4 500 30 6 100 1 5 0 1
735 0
0 3 10 100 10 50 10 10
Sample Output
735
630
0
0
Solution
多重背包问题
将第i种物品分成若干件物品,其中每件物品有一个系数,这件物品的费用和价值均是原来的费用和价值乘以这个系数。使这些系数分别为1,2,4,…,2^k−1,n[i]−2^k+1,且k是满足n[i]−2^k+1>0的最大整数。例如,如果n[i]为13,就将这种物品分成系数分别为1,2,4,6的四件物品。分成的这几件物品的系数和为n[i],表明不可能取多于n[i]件的第i种物品。另外这种方法也能保证对于0..n[i]间的每一个整数,均可以用若干个系数的和表示。这样就将一个多重背包问题转化为一个01背包问题了
Code
有各种不同面值的货币,每种面值的货币有不同的数量,请找出利用这些货币可以凑成的最接近且小于等于给定的数字cash的金额
Input
多组用例,以文件尾结束输入。
每组用例以cash N n1 D1 n2 D2 ..nN DN形式输入
(0<=cash<=100000,0<=N<=10,0<=ni<=1000,1<=nk<=1000)
cash为货币和上限,N为货币种类,ni和Di分别为每种货币的面额和数量
Output
对于每组用例,输出利用给出货币可以凑成的最接近的小于等于cash的金额
Sample Input
735 3 4 125 6 5 3 350
633 4 500 30 6 100 1 5 0 1
735 0
0 3 10 100 10 50 10 10
Sample Output
735
630
0
0
Solution
多重背包问题
将第i种物品分成若干件物品,其中每件物品有一个系数,这件物品的费用和价值均是原来的费用和价值乘以这个系数。使这些系数分别为1,2,4,…,2^k−1,n[i]−2^k+1,且k是满足n[i]−2^k+1>0的最大整数。例如,如果n[i]为13,就将这种物品分成系数分别为1,2,4,6的四件物品。分成的这几件物品的系数和为n[i],表明不可能取多于n[i]件的第i种物品。另外这种方法也能保证对于0..n[i]间的每一个整数,均可以用若干个系数的和表示。这样就将一个多重背包问题转化为一个01背包问题了
Code
#include<cstdio> #include<cstring> #include<iostream> using namespace std; #define INF (1<<29) #define maxn 1000010 int dp[maxn]; int n[230],w[230]; int b[11]={1,2,4,8,16,32,64,128,256,512,1024}; int ans,N; int main() { while(scanf("%d%d",&ans,&N)!=EOF) { memset(n,0,sizeof(n)); memset(w,0,sizeof(w)); memset(dp,0,sizeof(dp)); int count=1,i,j,k; for(int i=1;i<=N;i++) { int nn,ww; scanf("%d%d",&nn,&ww); if(nn!=0) { for(j=10;j>=0;j--) if(nn-b[j]+1>0) break; for(k=0;k<j;k++) { n[count]=b[k]; w[count]=ww*b[k]; count++; } n[count]=nn-b[j]+1; w[count]=ww*(nn-b[j]+1); count++; } } count--; for(i=1;i<=count;i++) for(j=ans;j>=w[i];j--) dp[j]=max(dp[j],dp[j-w[i]]+w[i]); printf("%d\n",dp[ans]); } return 0; }
相关文章推荐
- drawRect:和layoutSubview的区别
- 指针数组与数组指针
- 受托停止事件冒泡
- 完全用LINUX工作
- 随想--脾气
- Java正则表达式匹配
- 多线程 调用多线程的方法 Runtime与ProcessBuilder
- C语言链表实现——无限录入单词程序
- PHP钩子是什么?
- 安卓开发利用外部jar包时ClassNotFound的错误
- 15第十六周项目二——有些数的阶乘不算了
- 利用iptables开放被动模式下的FTP服务
- NYOJ 264--国王的魔镜
- Unity教程之再谈Unity中的优化技术
- MYSQL必知必会第13章SQL语句
- 黑马程序员--多线程学习日记
- Python字符串操作符(%s,%d,%u...)与输出格式控制(*-+#0...)
- 意义和公式的协方差
- int java.lang.String.hashCode()
- 做好准备,新开始