多重背包
http://acm.hdu.edu.cn/showproblem.php?pid=2844
题意:给你n种硬币和商品价格m,每种硬币给出价值和数量。问1-m价值中有多少种价值可以用这些硬币表示出来。
解法:因题目数据量较大,必须二进制拆分成01背包优化。
最后遍历所以容量,如果价值等于容量则表示该价格可以表示。
//#include <bits/stdc++.h>
#include <cstdio>
#include <cstring>
#include <cmath>
#include <algorithm>
#include <iostream>
#include <cstdio>
#include <string>
#include <stdio.h>
#include <queue>
#include <stack>
#include <map>
#include <set>
#include <string.h>
#include <vector>
#define ME(x , y) memset(x , y , sizeof(x))
#define SF(n) scanf("%d" , &n)
#define rep(i , n) for(int i = 0 ; i < n ; i ++)
#define INF 0x3f3f3f3f
#define mod 1000000007
#define PI acos(-1)
using namespace std;
typedef long long ll ;
int a[109] , b[109] , val[100009];
int dp[100009];
int main()
{
/*#ifdef ONLINE_JUDGE
#else
freopen("D:/c++/in.txt", "r", stdin);
freopen("D:/c++/out.txt", "w", stdout);
#endif*/
int n , v ;
while(~scanf("%d%d" , &n , &v) && n+v)
{
for(int i = 1 ; i <= n ; i++)
{
scanf("%d" , &a[i]);
}
for(int i = 1 ; i <= n ; i++)
{
scanf("%d" , &b[i]);
}
memset(dp , 0 , sizeof(dp));
int l = 1 ;
for(int i = 1 ; i <= n ; i++)
{
int c = 1;
while(b[i] - c > 0)
{
val[l++] = c * a[i];
b[i] -= c ;
c *= 2 ;
}
val[l++] = b[i] * a[i];
}
for(int i = 1 ; i < l ; i++)
{
for(int j = v ; j >= val[i] ; j--)
{
dp[j] = max(dp[j] , dp[j-val[i]]+val[i]);
}
}
int ans = 0 ;
for(int i = 1 ; i <= v ; i++)
{
if(dp[i] == i)
{
ans ++ ;
}
}
cout << ans << endl ;
}
return 0 ;
}

浙公网安备 33010602011771号