hdu1085(母函数/完全背包)

该博客主要介绍了如何利用母函数和完全背包的方法解决HDU1085题,即在给定1元、2元、5元硬币数量的情况下,找出最小的无法组合成的面值。当硬币总数对应的面值都能被组合时,最小未组合的面值是总和加1。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

题目链接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;
}


评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值