0-1背包变形:容量恰好用完
类比:容量:给定的总面值sum、邮票[i]的重量:面值w[i] 、价值:均为1
第i轮 dp[j]:前i张邮票凑出总面值为j的最少张数
- 初始状态:dp[0]=0; dp[i]=INF(0<i<=sum) 表示无法完成
- 递推关系:dp[j]=min(dp[j],dp[j-w[i]]+1)
#include<iostream>
#include<cstring>
using namespace std;
const int maxn=101;
const int INF=0x7fffffff;
int w[maxn];
int dp[maxn];
int best(int sum,int n){
dp[0]=0;//初始化
for(int i=1;i<=sum;i++){
dp[i]=INF;
}
for(int i=1;i<=n;i++){
for(int j=sum;j>=w[i];j--){//从后往前更新
if(dp[j-w[i]]!=INF)dp[j]=min(dp[j],dp[j-w[i]]+1);//if避免加法上溢
}
}
if(dp[sum]==INF)dp[sum]=0;
return dp[sum];
}
int main(){
int sum,n;
while(scanf("%d%d",&sum,&n)!=EOF){
for(int i=1;i<=n;i++)scanf("%d",&w[i]);
printf("%d\n",best(sum,n));
}
}