POJ1742 Coins 多重背包+贪心

Posted forward777

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了POJ1742 Coins 多重背包+贪心相关的知识,希望对你有一定的参考价值。

Vjudge传送门

 

$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$

技术图片
 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 
View Code

 

以上是关于POJ1742 Coins 多重背包+贪心的主要内容,如果未能解决你的问题,请参考以下文章

POJ 1742 Coins 多重背包DP

poj1742 Coins(多重背包+单调队列优化)

POJ 1742 Coins ( 经典多重部分和问题 && DP || 多重背包 )

poj1742 Coins

POJ1742 Coins(男人八题之一)

hdu 2844 poj 1742 Coins