最小邮票数
题目描述
有若干张邮票,要求从中选取最少的邮票张数凑成一个给定的总值。 如,有1分,3分,3分,3分,4分五张邮票,要求凑成10分,则使用3张邮票:3分、3分、4分即可。
输入描述:
有多组数据,对于每组数据,首先是要求凑成的邮票总值M,M<100。然后是一个数N,N〈20,表示有N张邮票。接下来是N个正整数,分别表示这N张邮票的面值,且以升序排列。
输出描述:
对于每组数据,能够凑成总值M的最少邮票张数。若无解,输出0。
起初的想法类似于先从小到大排序,然后每次使用面额最大的邮票,类似于count[sum] = count[sum - maxNumber] + 1。 发现AC不过,然后突然想到如果面值是5,8,9。要凑总数13的话,那我肯定错了。
仔细一想,其实就是动态规划。
给出错误代码:
#include<iostream> using namespace std; int assemble(int number, int arr[], int rear) { if(number == 0) { return 0; }else if(number < 0) { return 27; } while(arr[rear] > number) { rear--; } rear--; return assemble(number - arr[rear + 1], arr, rear) + 1; } int main() { int m, n, rear; while(cin>>m>>n) { rear = n; int arr[n]; int i = 0; while(rear) { cin>>arr[i]; rear--; i++; } int out = assemble(m, arr, n - 1); if(out >= 20) { cout<<0; } else { cout<<out; } } }
再给出AC代码:
#include<iostream> #include<vector> #define mmax 27; using namespace std; int min(int a,int b){return a<b?a:b;} int main() { int m,n; while(cin>>m) { cin>>n; int c[n]; for(int i=0;i<n;i++) cin>>c[i]; int dp[m+1]; for(int i=0;i<=m;i++) dp[i]=mmax; dp[0]=0; for(int i=0;i<n;i++) { for(int j=m;j>=0;j--) { if(j-c[i]>=0&&dp[j-c[i]]!=mmax) { dp[j]=min(dp[j],dp[j-c[i]]+1); } } } if(dp[m]==mmax) cout<<0<<endl; else cout<<dp[m]<<endl; } }