邮票问题
【问题描述】
给定一个信封,最多只允许粘贴N(N<=100)张邮票,我们现在有m(m<=100)种邮票,面值分别为:x1,x2,…….xm分(xi<=255,为正整数),并假设各种邮票都有足够多张.
要求计算所能获得的邮资最大范围,即求最大值MAX,使在1—MAX之间的每一个邮资值都能得到.
例如:N=4,有2种邮票,面值分别为1分,4分,于是可以得到1----10分,和12分,13分,16分的邮资,由于不能得到11分和15分,所有邮资的最大范围是Max=10.
【样例输入】
从键盘输入一个文本文件的文件名,该文件第1行为最多粘贴的邮票数N;第2行为邮票种数m,以下m行各有一个数字,表示邮票的面值xi.如:
2 4
1
4
【样例输出】
Max=10
【算法分析】
递推:
设 :f[i] (f[i] 指 i 面值所需的最少张邮票)
起始值 f[1]=1;
开始判断有没有面值 1 的邮票,若没有直接输出;
我们举个例子,比如拿 5 来说
找出 5 能整除的一个邮票,且所有符合条件的邮票面值中它最大;f[i] 等于 5 除以它;
再用一个 for:
for(i=1;i<=i1/2;i++)
if(f[i1]>f[i]+f[i1-i]) f[i1]=f[i]+f[i1-i];
枚举出 i 面值用两个数所需的最少邮票的最小差;
5:1+4
5:2+3
#include<cstdio>
#include<iostream>
using namespace std;
int main()
{
int i,i1=0,n,m,a[10001],f[10001];
scanf("%d%d",&n,&m);
bool b=false;
for(i=1;i<=n;i++)
{
scanf("%d",&a[i]);
if(a[i]==1) b=true;
}
if(!b) printf("Max=0");
else
{
i1=1;f[i1]=1;
do{
i1++;
for(i=1;i<=n;i++)
if(i1%a[i]==0)
if(f[i1]==0)
f[i1]=i1/a[i];
else f[i1]=min(f[i1],i1/a[i]);
for(i=1;i<=i1/2;i++)
if(f[i1]>f[i]+f[i1-i]) f[i1]=f[i]+f[i1-i];
if(f[i1]>m || f[i1]==0) break;
}while(true);
printf("Max=%d",i1-1);
}
return 0;
}