hdu 2844 题解
题目大意:给定面值不同,数量不同的纸币,求所有可表示的钱数的总个数。
题目分析:完全背包问题,但是物品总数太多,需要先采用二进制优化一下。
代码解析:
#include<iostream>
#include<vector>
#include<cstring>
#include<algorithm>
#include<stdio.h>
#include<stdlib.h>
#include<queue>
using namespace std;
int v[105];
int c[1005];
int dp[100005];
vector<int> goods; //依次是物品的顺序,存储的是物品的体积。
int main()
{
intn, m, a, b, i, j;
while(scanf("%d%d", &n, &m ) && n )
{
intsum = 0;
for(i = 1; i <= n; i ++ ) scanf("%d", &v[i]);
for(j = 1; j <= n; j ++ ){
scanf("%d",&c[j]);
sum+= v[j]*c[j];
}
if(m > sum ) m = sum;
goods.clear();
memset(dp,0, sizeof(dp));
dp[0]= 1;
for(i = 1; i <= n; i ++ ){ //二进制优化
intt = 1;
while(c[i]-t> 0 ){
goods.push_back(t*v[i]);
c[i]-= t;
t*= 2;
}
if(c[i] != 0 ) goods.push_back(c[i]*v[i]);
}
for(i = 0; i < goods.size(); i ++ ) { //转化成01背包问题解决
for(j = m; j >= goods[i]; j -- ){
if(dp[j-goods[i]]){
dp[j]= true;
}
}
}
sum= 0;
for(i = 1; i <= m; i ++ ){
sum+= dp[i];
}
cout<<sum<<endl;
}
return0;
}