[POI2005]Bank notes

link

试题分析

我们发现此题是一个十分简单的多重背包。但是按照朴素写法会超时。所以要去考虑优化。

我们发现我们若$W=7$,可以拆成$1+2+4$,不用每次$1+1+1+1+1+1+1$,从$N$级就变成$log$级了。所以对于每一组$(w_i,c_i)$,我们都可以拆成多个二进制数,然后暴力去写即可。

时间复杂度:$O(k\times \sum_{i=1}^n log_2 C_i).$

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
inline int read(){
    int f=1,ans=0;char c=getchar();
    while(c<'0'||c>'9'){if(c=='-')f=-1;c=getchar();}
    while(c>='0'&&c<='9'){ans=ans*10+c-'0';c=getchar();}
    return f*ans;
}
const int N=1e6+1;
int n,w[N],c[N],f[N],k,W[N];
void solve(int wi,int ci,int numi){
    int t=1;
    while(numi>=t){
        w[++w[0]]=wi*t;
        c[++c[0]]=t;
        numi-=t;
        t<<=1;
    }
    w[++w[0]]=wi*numi;
    c[++c[0]]=numi;
    return;
}
int main(){
    n=read();
    for(int i=1;i<=n;i++) W[i]=read();
    for(int i=1;i<=n;i++){
        int num=read();
        solve(W[i],1,num);
    }
    memset(f,127/3,sizeof(f));f[0]=0;
    k=read();n=w[0];
    for(int i=1;i<=n;i++)
        for(int j=k;j>=w[i];j--) f[j]=min(f[j],f[j-w[i]]+c[i]); 
    cout<<f[k];
}
View Code

 

转载于:https://www.cnblogs.com/si-rui-yang/p/10139146.html

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值