题目链接Holding Bin-Laden Captive!
给定面值为 1, 2, 5的三种硬币和其数量num_1,num_2,num_3
求最小的不能由这几种硬币组成的面值
1、母函数
面值为1的coin
面值为2的coin
面值为3的coin
得到
展开后系数为0的x^n即其n实不能取到的面值
!!当(num_1+2*num_2+3*num_3)的某个面值都能取到时,最小的不能取到的是N+1
#include <iostream>
#include <stdio.h>
#include <memory.h>
using namespace std;
struct node
{
int val,num;
}coin[3];
const int maxn=1e4;
int c1[maxn],c2[maxn];
int main()
{
//freopen("in.txt","r",stdin);
int tot;
coin[0].val=1;coin[1].val=2;coin[2].val=5;
while(~scanf("%d%d%d", &coin[0].num, &coin[1].num, &coin[2].num) && (coin[0].num || coin[1].num || coin[2].num)){
tot=coin[0].num*coin[0].val+coin[1].num*coin[1].val+coin[2].num*coin[2].val;
memset(c1,0,sizeof(c1));
memset(c2,0,sizeof(c2));
for(int i=0;i<=coin[0].num;i++)c1[i]=1;
for(int i=1;i<3;i++){
for(int j=0;j<=tot;j++){
for(int k=0;k<=coin[i].num*coin[i].val&&k+j<=tot;k+=coin[i].val){
c2[j+k]+=c1[j];
}
}
for(int j=0;j<=tot;j++){
c1[j]=c2[j];
c2[j]=0;
}
}
int i;
for(i=0;i<=tot;i++){
if(!c1[i]){
break;
}
}
printf("%d\n",i);
}
return 0;
2、完全背包
cost和weight都是coin的面值1,2,5
#include <iostream>
#include <stdio.h>
#include <memory.h>
#include <algorithm>
using namespace std;
const int maxn=10005;
int V;
struct node
{
int val,num;
}coin[3];
int dp[maxn];
void ZeroOnePack(int C,int W)
{
for(int v=V;v>=C;v--){
dp[v]=max(dp[v],dp[v-C]+W);
}
}
void CompletePack(int C,int W)
{
for(int v=C;v<=V;v++){
dp[v]=max(dp[v],dp[v-C]+W);
}
}
void MultiplePack(int C,int W,int M)
{
if(C*M>=V){
CompletePack(C,W);
return;
}
int k=1;
while(k<M){
ZeroOnePack(k*C,k*W);
M=M-k;
k=k*2;
}
ZeroOnePack(M*C,M*W);
}
int main()
{
//freopen("in.txt","r",stdin);
coin[0].val=1;
coin[1].val=2;
coin[2].val=5;
while(scanf("%d%d%d",&coin[0].num,&coin[1].num,&coin[2].num)!=EOF&&(coin[0].num||coin[1].num||coin[2].num)){
memset(dp,0,sizeof(dp));
V=coin[0].num*coin[0].val+coin[1].num*coin[1].val+coin[2].num*coin[2].val;
for(int i=0;i<3;i++){
MultiplePack(coin[i].val,coin[i].val,coin[i].num);
}
int v;
for(v=0;v<=V;v++){
if(dp[v]!=v)break;
}
printf("%d\n",v);
}
return 0;
}