华师一附中OI组

 找回密码
 立即注册
搜索
热搜: 活动 交友 discuz
查看: 1716|回复: 4
打印 上一主题 下一主题

P2725 邮票 Stamps

[复制链接]

738

主题

1485

帖子

5422

积分

管理员

Rank: 9Rank: 9Rank: 9

积分
5422
跳转到指定楼层
楼主
发表于 2018-5-21 22:50:51 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
https://www.luogu.org/problemnew/show/P2725

题目背景
给一组 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。 [规模最大的一个点的时限是3s]

小提示:因为14贴不出来,所以最高上限是13而不是15

输入输出格式
输入格式:
第 1 行: 两个整数,K 和 N。K(1 <= K <= 200)是可用的邮票总数。N(1 <= N <= 50)是邮票面值的数量。

第 2 行 .. 文件末: N 个整数,每行 15 个,列出所有的 N 个邮票的面值,每张邮票的面值不超过 10000。

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

输入输出样例
输入样例#1:
5 2
1 3
输出样例#1:
13
说明
题目翻译来自NOCOW。

USACO Training Section 3.1
回复

使用道具 举报

9

主题

158

帖子

470

积分

华一学生

积分
470
QQ
沙发
发表于 2018-7-30 09:30:22 | 只看该作者
  1. #include<iostream>
  2. using namespace std;
  3. int k,n,dp[2000001],a,t;
  4. int main()
  5. {
  6.     cin>>k>>n;
  7.     for(int i=1;i<=2000000;i++)dp[i]=9999;
  8.     for(int i=1;i<=n;i++)
  9.     {
  10.         cin>>a;
  11.         for(int j=a;j<=2000000;j++)
  12.             if(dp[j-a]+1<=k)
  13.             dp[j]=min(dp[j],dp[j-a]+1);
  14.     }
  15.     while(dp[++t]!=9999);
  16.     cout<<t-1;
  17.     return 0;
  18. }
复制代码
回复 支持 反对

使用道具 举报

9

主题

89

帖子

292

积分

华一学生

积分
292
板凳
发表于 2018-7-31 23:35:24 | 只看该作者
  1. #include<iostream>
  2. using namespace std;
  3. int k,n,i,j;
  4. const int mx=55;
  5. int a[mx],dp[2000000];///dp[i]构成i至少需要的邮票数
  6. int main()
  7. {
  8.     cin>>k>>n;///最多k张邮票
  9.     for (i=1; i<=n; i++) cin>>a[i];
  10.     for (i=1;i<=2000000;i++) dp[i]=99999;
  11.     dp[0]=0;
  12.     for (i=1;i<=n;i++)
  13.     {
  14.         for (j=a[i];j<=2000000;j++)
  15.         {
  16.             if (dp[j-a[i]]+1<=k)///邮票数没有超出
  17.                 dp[j]=min(dp[j],dp[j-a[i]]+1);
  18.         }
  19.     }
  20.     int s;
  21.     for (i=1;i<=2000000;i++)
  22.     {
  23.         if (dp[i]==99999)
  24.             {s=i-1;break;}
  25.     }
  26.     cout<<s;
  27.     return 0;
  28. }
复制代码
回复 支持 反对

使用道具 举报

0

主题

31

帖子

94

积分

注册会员

Rank: 2

积分
94
地板
发表于 2018-8-1 22:16:56 | 只看该作者
  1. #include<cstdio>
  2. #include<algorithm>
  3. using namespace std;
  4. int n,k;
  5. int f[20000001];
  6. int a[51];
  7. const int INF=999999999;
  8. int ans;
  9. int main()
  10. {
  11.         scanf("%d%d",&k,&n);
  12.         for(int i=1;i<=2000000;i++)
  13.         {
  14.                 f[i]=INF;
  15.         }
  16.         f[0]=0;
  17.         for(int i=1;i<=n;i++)
  18.         {
  19.                 scanf("%d",&a[i]);
  20.         }
  21.         for(int i=1;i<=n;i++)
  22.         {
  23.                 for(int j=a[i];j<=2000000;j++)
  24.                 {
  25.                         if(f[j-a[i]]+1>k)
  26.                         {
  27.                                 continue;
  28.                         }
  29.                         else
  30.                         {
  31.                                 f[j]=min(f[j],f[j-a[i]]+1);
  32.                         }
  33.                 }
  34.         }
  35.         for(int i=1;i<=2000000;i++)
  36.         {
  37.                 if(f[i]==INF)
  38.                 {
  39.                         break;
  40.                 }
  41.                 ans++;
  42.         }
  43.         printf("%d",ans);
  44.         return 0;
  45. }
复制代码
回复 支持 反对

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

QQ|Archiver|手机版|小黑屋|服务支持:DZ动力|华师一附中OI组  

GMT+8, 2024-12-25 13:07 , Processed in 0.145068 second(s), 23 queries .

Powered by Discuz! X3.2

© 2001-2013 Comsenz Inc.

快速回复 返回顶部 返回列表