链接:http://poj.org/problem?id=1276
题意:给出一个n 代表最多拿的值为n, m种钱币, 每种有 x个, 值为y,问在不超过n的情况下最多能拿多少钱。
解题思路:也算是多重背包的模板题了,做法是将多重背包化成0 1背包, 将每种钱币分别分成 1个 2个 4个…..当不够分的时候就将剩下的也当作一组, 这样每一组都对应一个不同的值 y*1, y*2, y*4….然后直接0 1背包就行了, 注意不一定能装满,故我每一步都判断了下。
代码:
#include <iostream>
#include <algorithm>
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <math.h>
using namespace std;
const int Max=1100000;
int data[Max];
int dp[Max];
int mem;
int vjudge(int n, int x){//分解每一种(英语差,函数随便起的名...)
int flag=1;
while(1){
if(n>=flag){
n-=flag;
data[mem++]=x*flag;
flag*=2;
}
else {
data[mem++]=x*n;
break;
}
}
return 0;
}
int main()
{
int aim, n;
while(~scanf("%d%d", &aim, &n)){
mem=0;
int i, j;
memset(dp, 0, sizeof(dp));
for(int a=0; a<n; a++){
scanf("%d%d", &i, &j);
vjudge(i, j);
}
// for(int a=0; a<mem; a++){
// printf("%d ", data[a]);
// }
int ans=0;
for(int a=0; a<mem; a++){
for(int b=aim; b>=data[a]; b--){
dp[b]=max(dp[b], dp[b-data[a]]+data[a]);
ans=max(dp[b], ans);
}
}
printf("%d\n", ans);
}
return 0;
}