惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

M
MIT News - Artificial intelligence
WordPress大学
WordPress大学
GbyAI
GbyAI
S
SegmentFault 最新的问题
量子位
爱范儿
爱范儿
OSCHINA 社区最新新闻
OSCHINA 社区最新新闻
MyScale Blog
MyScale Blog
人人都是产品经理
人人都是产品经理
博客园 - 叶小钗
aimingoo的专栏
aimingoo的专栏
V
Visual Studio Blog
U
Unit 42
Cyber Security Advisories - MS-ISAC
Cyber Security Advisories - MS-ISAC
The Cloudflare Blog
Stack Overflow Blog
Stack Overflow Blog
博客园 - 聂微东
J
Java Code Geeks
The GitHub Blog
The GitHub Blog
Y
Y Combinator Blog
IT之家
IT之家
Martin Fowler
Martin Fowler
宝玉的分享
宝玉的分享
雷峰网
雷峰网

博客园 - zealsoft

洛谷 P1816 忠诚题解 洛谷 P2384 最短路题解 洛谷 P2722 总分题解 洛谷 P1219 八皇后题解 洛谷 P2921 在农场万圣节Trick or Treat on the Farm题解 洛谷 P1162 填涂颜色题解 洛谷 P1330 封锁阳光大学题解 洛谷 P1032 字串变换题解 洛谷 P1443 马的遍历题解 洛谷 P1280 尼克的任务题解 洛谷 P1020导弹拦截题解 洛谷 P1141 01迷宫题解 VisualSVNServer无法卸载也无法安装,报告不是有效的MOF文件(0x8004401e)错误 视频捕捉的格式问题 一个VxWorks源代码网站 找个轻量级的Log库还挺难 TAU G2中的BitString和OctetString W32.Downadup.autorun病毒的清除 如何用Visual Studio 2005编译Wireshark的插件
洛谷 P2725 邮票题解
zealsoft · 2019-08-31 · via 博客园 - zealsoft

题目背景

给一组 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 张邮票贴出的邮资数。

输入输出样例

说明/提示

题目翻译来自NOCOW。

USACO Training Section 3.1


题解

这题虽然也是完全背包问题,但是比总分那题难想。直接选择题目所求作为f[i]是不行的。f[i]为要达成i面值所需要的最少邮票个数。这样状态转移方程就是:f[j] = min( f[j], f[j - a] + 1 );,也就是如果选择面值为a可以减少张数就选择a,否则不选a。

 1 #include <iostream>
 2 #include <stdio.h>
 3 #include <math.h>
 4 #include <algorithm>
 5 #include <string.h>
 6 
 7 using namespace std;
 8 
 9 const int    MAXN = 2000005;
10 int        a, n, k, f[MAXN];
11 
12 int main()
13 {
14     cin >> k >> n;
15     for ( int i = 0; i < MAXN; i++ )
16     {
17         f[i] = 1111111;
18     }
19     f[0] = 0;
20     for ( int i = 1; i <= n; i++ )
21     {
22         cin >> a;
23         for ( int j = a; j <= MAXN; j++ )
24         {
25             if ( f[j - a] + 1 <= k ) /* 用的邮票数目在范围内 */
26             {
27                 f[j] = min( f[j], f[j - a] + 1 );
28             }
29         }
30     }
31     for ( int i = 1; i < MAXN; i++ )
32     {
33         if ( f[i] == 1111111 )
34         {
35             cout << i - 1 << endl;
36             break;
37         }
38     }
39     return(0);
40 }