hdu2844 Coins 多重背包+完全背包

来源:互联网 发布:淘宝账号为什么被冻结 编辑:程序博客网 时间:2024/06/05 02:15
//这题的意思就是有n种硬币,每种硬币有价值a和数量c//要求购买一件价值不超过m的商品,购买的时候不找零//求可能购买的商品的价值//典型的背包问题,价值和重量相等的背包//dp[i][j] = max(dp[i-1][j],dp[i-1][j-a[i]]+a[i];//但是每件物品还有数量这个属性,所以直接用多重背包//二进制转换成一重背包做。这样直接做的结果就是,,//超时,我疑惑不已,然后看了一下题解,恍然大悟,//如果a[i]*c[i]>=m时,这时候还用二进制转换作甚?//明显直接可以按照完全背包做啊,这样等价的看成这种//硬币无限多的情况,然后就ac啦~哈哈哈哈//继续练吧~#include <algorithm>#include <bitset>#include <cassert>#include <cctype>#include <cfloat>#include <climits>#include <cmath>#include <complex>#include <cstdio>#include <cstdlib>#include <cstring>#include <ctime>#include <deque>#include <functional>#include <iostream>#include <list>#include <map>#include <numeric>#include <queue>#include <set>#include <stack>#include <vector>#define ceil(a,b) (((a)+(b)-1)/(b))#define endl '\n'#define gcd __gcd#define highBit(x) (1ULL<<(63-__builtin_clzll(x)))#define popCount __builtin_popcountlltypedef long long ll;using namespace std;const int MOD = 1000000007;const long double PI = acos(-1.L);template<class T> inline T lcm(const T& a, const T& b) { return a/gcd(a, b)*b; }template<class T> inline T lowBit(const T& x) { return x&-x; }template<class T> inline T maximize(T& a, const T& b) { return a=a<b?b:a; }template<class T> inline T minimize(T& a, const T& b) { return a=a<b?a:b; }const int maxn = 108;int a[maxn];int c[maxn];int dp[100009];int n,m;int pa[maxn*1000];int cnt;void init(){for (int i=1;i<=n;i++)scanf("%d",&a[i]);for (int i=1;i<=n;i++)scanf("%d",&c[i]);cnt = 0;memset(dp,0,sizeof(dp));for (int i=1;i<=n;i++){if (c[i]*a[i]>=m){for (int j=a[i];j<=m;j++)dp[j]=max(dp[j],dp[j-a[i]]+a[i]);}else {int t = 1;while(t<c[i]){pa[cnt++]=a[i]*t;c[i]-=t;t*=2;}if (c[i])pa[cnt++]=a[i]*c[i];}}}void solve(){for (int i=0;i<cnt;i++){for (int j=m;j>=pa[i];j--)dp[j]=max(dp[j],dp[j-pa[i]]+pa[i]);}int ans = 0;for (int i=1;i<=m;i++)if (dp[i]==i)ans++;printf("%d\n",ans);}int main() {   // freopen("G:\\Code\\1.txt","r",stdin);while(scanf("%d%d",&n,&m)!=EOF){if (n==0&&m==0)break;init();solve();}return 0;}

0 0
原创粉丝点击