【题解】邮票

题目描述

给一组N枚邮票的面值集合(如,{1分,3分})和一个上限K——表示信封上能够贴K张邮票。计算从1到M的最大连续可贴出的邮资。
例如,假设有1分和3分的邮票;你最多可以贴5张邮票。很容易贴出1到5分的邮资(用1分邮票贴就行了),接下来的邮资也不难:
stamps
然而,使用5枚1分或者3分的邮票根本不可能贴出14分的邮资。因此,对于这两种邮票的集合和上限K=5,答案是M=13。
(规模最大的一个点的时限是3s)
小提示:因为14贴不出来,所以最高上限是13而不是15。

输入输出格式

输入格式:

第1行,两个整数,K和N。K(1≤K≤200)是可用的邮票总数。N(1≤N≤50)是邮票面值的数量。
第2行至末尾:N个整数,每行15个,列出所有的N个邮票的面值,每张邮票的面值不超过10000。

输出格式:

一行,一个整数,从1分开始连续的可用集合中不多于K张邮票贴出的邮资数。

输入输出样例

输入样例:

5 2
1 3

输出样例:

13

这道题是一道简(jv)单(nan)的DP题
dp[i]表示面值为i的邮资至少用dp[i]张邮票表示
因为dp[i]的值就是i-a[j]元邮资加a[j]这张邮票
所以得到动态转移方程:

dp[i]=min(dp[i],dp[i-a[j]]+1);

代码:

#include<iostream>
using namespace std;
long long k,n,a[55],ans,dp[10000005];
int main()
{
	cin>>k>>n;
	for(register int i=1;i<=n;++i) cin>>a[i];
	for(register int i=1;;++i)
	{
		dp[i]=2147483647;
		for(register int j=1;j<=n;++j) if(i-a[j]>=0) dp[i]=min(dp[i],dp[i-a[j]]+1);
		if(dp[i]>k)
		{
			ans=i-1;
			break;
		}
	}
	cout<<ans;
}
原文地址:https://www.cnblogs.com/2021-yanghaoran/p/11934921.html