标签:
Time Limit: 1000MS | Memory Limit: 10000K | |
Total Submissions: 28826 | Accepted: 10310 |
Description
Input
Output
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
题意:给若干种面值的纸币,第i种纸币有n[i]张,每张面值为D[i],问拼凑出不超过cash的最大面值是多少
思路:很明显这是一个多重背包(每种纸币的数量是有限的),用二进制优化并转化为01背包解决,如果某种纸币的可拼凑出的面值超过了cash,则看成其数量是无限的,当成完全背包处理,反之则是有限的,用二进制优化当成01背包处理
#include<iostream> #include<cstdio> #include<cstring> #include<cstdlib> #include<algorithm> using namespace std; const int maxn=1000100; int cash,N; int n[maxn],D[maxn]; int dp[maxn]; void ZeroOnePack(int weight,int val) { for(int i=cash;i>=weight;i--){ dp[i]=max(dp[i],dp[i-weight]+val); } } void CompletePack(int weight,int val) { for(int i=weight;i<=cash;i++){ dp[i]=max(dp[i],dp[i-weight]+val); } } void MultiPack(int weight,int val,int amount) { if(weight*amount>=cash) CompletePack(weight,val);//如果超过限制,当完全背包处理 else{ //否则用二进制优化并转为01背包处理 int k=1; while(k<amount){//按k=1,2,4,...的顺序分解amount,对分解后的部分按01背包处理 ZeroOnePack(k*weight,k*val); amount-=k; k*=2; } ZeroOnePack(amount*weight,amount*val); //剩下部分也按01背包处理 } } int main() { while(cin>>cash>>N){ memset(dp,0,sizeof(dp)); for(int i=1;i<=N;i++){ cin>>n[i]>>D[i]; MultiPack(D[i],D[i],n[i]); } cout<<dp[cash]<<endl; } return 0; }
标签:
原文地址:http://www.cnblogs.com/--560/p/4348716.html