显然这是一道背包 。但是这道题不是朴素的 与无穷,因为题目规定了对于 种物品一共最多用 次,所以我们是无法通过一般的背包模型来完成这道题的。
但是这道题始终有背包 的感觉,那么我们不妨就从背包的角度来想想这道题。
由于朴素的背包定义的为:
表示能否填充使得空间(价值)恰好为 ,对应的转移方程:
对于这道题,我们只需要稍微变换一下思路就可以求解了。
表示填充使得价值为I时所使用的物品数量,这样来想思路其实就一下子畅通了,而相对应的转移方程也就很容易写出来:
初始化就是 。
对于每一个空间 ,我们在状态转移结束后判断 是否小于等于 ,不然就表明填充到空间 的时候,所需要的个数就大于 了,那么 就是我们需要的答案。
#include <bits/stdc++.h>
#define For(I,L,R) for(I=(L);I<=(R);I++)
using namespace std;
inline int Read(){
int X=0;char CH=getchar();bool F=0;
while(CH>'9'||CH<'0'){if(CH=='-')F=1;CH=getchar();}
while(CH>='0'&&CH<='9'){X=(X<<1)+(X<<3)+CH-'0';CH=getchar();}
return F?-X:X;
}
const int Max=2e6+5;
const int Inf=1e9;
int N,M,V[Max],DP[Max];
int main(){
int I,J,K;
N=Read(),M=Read();
For(I,1,M) V[I]=Read();
For(I,1,2000000) {
DP[I]=Inf;
For(J,1,M) if(I>=V[J])
DP[I]=min(DP[I],DP[I-V[J]]+1);
if(DP[I]>N){
printf("%d\n",I-1);return 0;
}
}
return 0;
}