题目描述
有若干张邮票,要求从中选取最少的邮票张数凑成一个给定的总值。 如,有1分,3分,3分,3分,4分五张邮票,要求凑成10分,则使用3张邮票:3分、3分、4分即可。
输入描述:
有多组数据,对于每组数据,首先是要求凑成的邮票总值M,M<100。然后是一个数N,N〈20,表示有N张邮票。接下来是N个正整数,分别表示这N张邮票的面值,且以升序排列。
输出描述:
对于每组数据,能够凑成总值M的最少邮票张数。若无解,输出0。
示例1
输入
1051 3 3 3 4
输出
3
//此题是动态规划类型的题目,每次都可以选择拿邮票或者
//不拿邮票。dp[j]是当总和<=j时的邮票的数量。
//状态转移方程为dp[j]=min(dp[j],dp[j-v[i]]+1);
//或者是不取当前邮票,或者是取
#include<iostream>
const int maxx=99999;
using namespace std;
int v[1000],dp[120];
int main()
{
int m;
while(cin>>m)
{
int n;
cin>>n;
for(int i=1;i<=n;i++)
cin>>v[i];
for(int j=0;j<=m;j++)
dp[j]=maxx;//初始化数量为最大值
dp[0]=0;
for(int i=1;i<=n;i++)
{
for(int j=m;j>=v[i];j--)
{
dp[j]=min(dp[j],dp[j-v[i]]+1);
}
}
if(dp[m]>10000)cout<<"0"<<endl;
else cout<<dp[m]<<endl;
}
return 0;
}
//dp如果是二维数组的话
#include<iostream>
const int maxx=999999;
using namespace std;
int value[50];//邮票的面值
int dp[25][110];//dp[i][j]表示第i张邮票凑成j面值的邮票张数
int main()
{
int sum;
int num;
while(cin>>sum)
{
cin>>num;
if(num==0)
{
cout<<"0"<<endl;
break;
}
for(int i=1;i<=num;i++)
{
cin>>value[i];
}
for(int i=0;i<=num;i++)
dp[i][0]=0;
for(int j=0;j<=sum;j++)
{
dp[0][j]=maxx;
}
for(int i=1;i<=num;i++)
{
for(int j=1;j<=sum;j++)
{
if(j<value[i])
{
dp[i][j]=dp[i-1][j];
}
else dp[i][j]=min(dp[i-1][j],dp[i-1][j-value[i]]+1);
}
}
if(dp[num][sum]==maxx)cout<<"0"<<endl;
else cout<<dp[num][sum]<<endl;
}
}