邮票

邮票

Time Limit:   1500MS       Memory Limit:   65535KB
Submissions:   227       Accepted:   46

 

Description

已知一个 N 枚邮票的面值集合(如,{1 分,3 分})和一个上限 K —— 表示信封上能够贴 K 张邮票。计算从 1 到 M 的最大连续可贴出的邮资。

例如,假设有 1 分和 3 分的邮票;你最多可以贴 5 张邮票。很容易贴出 1 到 5 分的邮资(用 1 分邮票贴就行了),接下来的邮资也不难:

6 = 3 + 3
7 = 3 + 3 + 1
8 = 3 + 3 + 1 + 1
9 = 3 + 3 + 3
10 = 3 + 3 + 3 + 1
11 = 3 + 3 + 3 + 1 + 1
12 = 3 + 3 + 3 + 3
13 = 3 + 3 + 3 + 3 + 1

 
然而,使用 5 枚 1 分或者 3 分的邮票根本不可能贴出 14 分的邮资。因此,对于这两种邮票的集合和上限 K=5,答案是 M=13。

Input

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

Output

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

Sample Input

5 2
1 3

Sample Output

13

解析:
大致题意:就是用所给的邮票面值,在不多于K张的范围内,最多能连续贴到多少.
大致思路:这道题的面值可以多次使用,很明显的多重背包;那这里就用DP来解决吧,代码如下:
# include<stdio.h>//DP,多重背包
# define M 9999999
int sign[55],f[2000005];
int min(int a,int b)
{
    return (a<b?a:b);
}
int main()
{
    int num,n,i,j;
    scanf("%d %d",&num,&n);
    for(i=0;i<n;i++)
        scanf("%d",&sign[i]);
    f[0]=0;
     for(i=1;;i++)
     {
         f[i]=M;
         for(j=0;j<n;j++)
            if(sign[j]<=i)     
            f[i] = min(f[i],f[i-sign[j]]+1);  
        if(f[i]>num)//如果最小的数目都超过了num,那这个i就一定贴不出  
        break;  
     }   
     printf("%d\n",i-1);   
     return 0;
}

 

posted on 2013-02-26 12:47  即为将军  阅读(293)  评论(0)    收藏  举报

导航