POJ1742 Coins 多重背包+贪心
Sol
首先发现这是一个多重背包,所以可以用多重背包的一般解法(直接拆分法,二进制拆分法...)
但事实是会TLE,只能另寻出路
本题仅关注“可行性”(面值能否拼成)而不是“最优性”,这是一个特殊之处。
从这里找优化
在“最优性”的问题中,f[j]从f[j]或f[j−a[i]]中转移而来;而在这样的“可行性”问题中,其实只要f[j]可行,我们就可以不用考虑f[j−a[i]了,也可以反过来说。
于是我们可以考虑一种贪心策略,设used[j]表示f[j]在阶段i时为True至少要用多少枚第i中硬币。
f[j]优先考虑由f[j]转移而来,而不是f[j−a[i]],这样就尽量减少了第i种硬币的使用数量。
其实还可以在作一个小优化,就是直接把used[j]的值存在f[j]中,f[]初始为−1,意为不能表示。
Code
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 #include<iostream> 2 #include<cstdio> 3 #define Rg register 4 #define il inline 5 #define db double 6 #define ll long long 7 #define go(i,a,b) for(Rg int i=a;i<=b;i++) 8 #define yes(i,a,b) for(Rg int i=a;i>=b;i--) 9 using namespace std; 10 il int read() 11 { 12 int x=0,y=1;char c=getchar(); 13 while(c<'0'||c>'9'){if(c=='-')y=-1;c=getchar();} 14 while(c>='0'&&c<='9'){x=(x<<3)+(x<<1)+c-'0';c=getchar();} 15 return x*y; 16 } 17 const int N=101; 18 int n,m,a[N],c[N],f[100001]; 19 ll ans; 20 il void sol() 21 { 22 go(i,1,m)f[i]=-1; 23 go(i,1,n) 24 go(j,0,m) 25 { 26 if(f[j]>=0)f[j]=c[i];//f[0]=c[i]可以看成是初始化 27 else if(j>=a[i]&&f[j-a[i]]>0)f[j]=f[j-a[i]]-1;//第i种硬币还有剩余 28 } 29 go(i,1,m)if(f[i]>=0)ans++; 30 } 31 int main() 32 { 33 while(1) 34 { 35 n=read(),m=read();ans=0; 36 if(!n&&!m)break; 37 go(i,1,n)a[i]=read();go(i,1,n)c[i]=read(); 38 sol();printf("%lld\n",ans); 39 } 40 return 0; 41 }
光伴随的阴影
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】凌霞软件回馈社区,博客园 & 1Panel & Halo 联合会员上线
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】博客园社区专享云产品让利特惠,阿里云新客6.5折上折
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步