杭电2844(背包+进制的处理)。

点击打开链接

题目意思:

要求你再给出的M范围(1~M),分别用给出的钱币,以及所对应的数量。求出看能并凑出的钱数有多少在(1~M)之间,包括边界。。

此题一看就应该可以猜到是用DP做,还有就是可以想到利用母函数。但是再看看数据,就可以排除一般DP,还有就是母函数的M值太大,可能会超时,因此这也是不可行的。

因此就看看DP可以完成了吗!!但是若直接DP可能也会数据就太大,因此也就要分开考虑。—:当一组数据的乘积大于M是,和当小于时,这里就分开考虑.

当数据积大于时,你就可以用完全背包(可以无限利用)直到不符合条件。二:就是小于时,当前的价值是加还是不加都有可能产生不同的结果。因此就可以利用01背包(加或者不加)的方法解决。

接着就是看代码:(细看代码)

#include<iostream>
#include<cstring>
#include<cstdio>
#include<algorithm>
#include<cmath>
#include<cstdlib>
using  namespace std;
const int maxn=100005;
int a[105],c[105];
int dp[maxn];
int n,m;
void compty(int x)//完全背包。
{
    int i;
    for(i=x;i<=m;i++)
        dp[i]=max(dp[i],dp[i-x]);
}
void beibao_01(int x)//01背包。可以看着次数。
{
    int i;
   for(i=m;i>=x;i--)
   {
       dp[i]=max(dp[i],dp[i-x]);
   }
}
void shuju(int cons,int n)
{
    int k;
    if(cons*n>m)//当输入的数据大于总的M时,应该考虑可以加入的次数,就是(转换妫完全背包题),完全背包,可以去好多次,直到不满足条件为止!
    compty(cons);
    else
    {
        k=1;
        while(k<n)//当然在小于时就必须考虑这依次是否家还是不加,这就考虑的是01背包的问题。
        {
            beibao_01(cons*k);
            n-=k;
            k++;
        }
        beibao_01(cons*n);
    }
}
int main()
{
    int i,j;
    while(scanf("%d%d",&n,&m)!=EOF)
    {
        if(n==0&&m==0)break;
        memset(a,0,sizeof(a));
        memset(c,0,sizeof(c));
        for(i=1;i<=n;i++)scanf("%d",&a[i]);
        for(i=1;i<=n;i++)scanf("%d",&c[i]);
        memset(dp,0,sizeof(dp));//初始化,
        dp[0]=1;
        for(i=1;i<=n;i++)
        {
           shuju(a[i],c[i]);//依次考虑,分别对你每一个数据谈论!!
        }
        int sum=0;
         for(i=1;i<=m;i++)
         {
             if(dp[i])
             sum++;

         }
        cout<<sum<<endl;
    }
    return 0;
}


 

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值