清华机试-最小邮票数

题目描述

有若干张邮票,要求从中选取最少的邮票张数凑成一个给定的总值。     如,有1分,3分,3分,3分,4分五张邮票,要求凑成10分,则使用3张邮票:3分、3分、4分即可。

输入描述:

有多组数据,对于每组数据,首先是要求凑成的邮票总值M,M<100。然后是一个数N,N〈 20,表示有N张邮票。接下来是N个正整数,分别表示这N张邮票的面值,且以升序排列。

输出描述:

对于每组数据,能够凑成总值M的最少邮票张数。若无解,输出0。

示例1

输入

10

5

1 3 3 3 4

输出

3

解题思路

一开始看到这个题目,想到的是bfs。bfs的思路是:枚举所有的可能性,最多有2的19次方种情况(524288种)。可以从0列到524287,一个数的二进制形式表示选或者不选这张邮票。由于对于每一个数字最多要列举19位,所以时间复杂度大约是O(19*2^19)。比较高但是应该也是可以通过的,因为其实有一些数字不用列举那么多位。

后来想到可以用动态规划来解决这个问题。如果将状态dp[i][j]定义为前i张邮票凑成总值j所需要的最少邮票数。则状态可以初始化为dp[i][0]=0。(其中,1<=i<N,0<=j<M)。

状态转移方程如下:

dp[i][j] = min(dp[i-1][j],dp[i-1][j-v[i]])。(其中,i>0,j-v[i]>=0)

同时注意判断dp[i][j]是否等于-1。-1表示dp[i][j]无解。

代码

#include <iostream>

#include <cmath>

using namespace std;

int dp[20][100] = {-1};

int num[20];

int main()

{

    cout << pow(2,19) * 19 << endl;

    int m,n;

    while(cin >> m >> n)

    {

        int ans = 20;

        for(int i = 0;i < n;i++)

        {

            dp[i][0] = 0;

            for(int j = 1;j <= m;j++)

                dp[i][j] = -1;

        }

        for(int i = 0;i < n;i++)

            cin >> num[i];

        for(int i = 0;i < n;i++)

        {

            for(int j = num[i];j <= m;j++)

            {

                if(i == 0)

                {

                    if(j == num[i]) dp[i][j] = 1;

                    else dp[i][j] = -1;

                }

                else

                {

                    int a = 20;

                    if(dp[i - 1][j - num[i]] != -1)

                        a = dp[i - 1][j - num[i]] + 1;

                    int b = 20;

                    if(dp[i - 1][j] != -1)

                        b = dp[i - 1][j];

                    int c = min(a,b);

                    if(c == 20) dp[i][j] = -1;

                    else dp[i][j] = c;

                }

            }

        }

        if(dp[n - 1][m] == -1) cout << 0 << endl;

        else cout << dp[n - 1][m] << endl;

    }

    return 0;

}

  

原文地址:https://www.cnblogs.com/tracy520/p/8836340.html

时间: 2024-10-08 00:26:19

清华机试-最小邮票数的相关文章

题目1209:最小邮票数

最小邮票数 题目描述: 有若干张邮票,要求从中选取最少的邮票张数凑成一个给定的总值.    如,有1分,3分,3分,3分,4分五张邮票,要求凑成10分,则使用3张邮票:3分.3分.4分即可. 输入: 有多组数据,对于每组数据,首先是要求凑成的邮票总值M,M<100.然后是一个数N,N〈20,表示有N张邮票.接下来是N个正整数,分别表示这N张邮票的面值,且以升序排列. 输出: 对于每组数据,能够凑成总值M的最少邮票张数.若无解,输出0. 样例输入: 10 5 1 3 3 3 4 样例输出: 3 S

算法练习之---最小邮票数

前言: 关于这种巧妙的排列组合类的算法问题,需要找到这种问题求解的特点,然后根据这种特点逐步求解的过程.在本问题中,要求解和一致情况下的组合数最小,这里我定义一个和sum长度一致的数组存放结果值,双重循环遍历完张数的总个数,在其中的第二层从sum值开始递减,逐渐找最小,最后输出数组中的结果位即可. 题目描述 有若干张邮票,要求从中选取最少的邮票张数凑成一个给定的总值.     如,有1分,3分,3分,3分,4分五张邮票,要求凑成10分,则使用3张邮票:3分.3分.4分即可. 输入描述:    

清华机试-玛雅人的密码(广搜)

题目描述 玛雅人有一种密码,如果字符串中出现连续的2012四个数字就能解开密码.给一个长度为N的字符串,(2=<N<=13)该字符串中只含有0,1,2三种数字,问这个字符串要移位几次才能解开密码,每次只能移动相邻的两个数字.例如02120经过一次移位,可以得到20120,01220,02210,02102,其中20120符合要求,因此输出为1.如果无论移位多少次都解不开密码,输出-1. 输入描述: 输入包含多组测试数据,每组测试数据由两行组成. 第一行为一个整数N,代表字符串的长度(2<

【转】朱兆祺教你如何攻破C语言学习、笔试与机试的难点(连载)

原文网址:http://bbs.elecfans.com/jishu_354666_1_1.html 再过1个月又是一年应届毕业生应聘的高峰期了,为了方便应届毕业生应聘,笔者将大学四年C语言知识及去年本人C语言笔试难点进行梳理,希望能对今年应届毕业生的应聘有所帮助. 2013年10月18日更新-->    攻破C语言这个帖子更新到这里,我不仅仅是为了补充大学学生遗漏的知识,我更重要的是希望通过我的经验,你们实际项目中的C语言写得漂亮,写出属于你的风格.“朱兆祺STM32手记”(http://bb

华为机试 宝典3 —擂台实战

首先推荐一个网站:acm.xidian.edu.cn/land/,上面的很多题目,难度很适合机试,如: 很简单:1031,1120,1122,1121,1103,1104,1281, 简单:1049,1181,1182,1279,1280, 中等:1106,1108,1183,1288. 难:1105,1282,1283, 大家可以根据自己的水平去训练,其实里面的难题也是很简单的,归类到题库中的话都属于简单题,只要好好看书学习都是可以做出来的,下面放几道例题,这些题都是机试很有可能考的题目,或者

华为校招机试—传送门

华为机试-多个数的最大公约数 华为机试-算日期 华为机试-拼音翻译成阿拉伯数字(只有数字拼音) 华为机试-拼音翻译成阿拉伯数字(有Wan,Qian,Bai,Shi单位) 华为机试-输出大写字母 华为机试-亮着电灯的盏数(优化过的双重for) 华为机试-从考试成绩中划出及格线 华为机试-亮着电灯的盏数(1-N完全平方数的个数) 华为机试-大数相减 华为机试-姓名的夫妻相 华为机试-元素按奇偶排序 (金字塔) 华为机试-地铁换乘(图文吐血整理) 华为机试-"十七进制"转"十进制&

清华大学软件2016机试

机试完几天了,两个月的准备就是为了这三小时的三道题,趁着没忘记,把题目贡献出来,也算是继承学长的光荣传统,泽被后人吧! 1.大数乘法 先输入一个数字m,表示后面将输入m个数,接着输入m个0到9的数,以空格隔开(至少有一个不为0),这些数可构成一个十进制数a, a的三次方为数b, 求b的各个位的数字,输出时以空格隔开,不要输出多余的空格. 输入示例: 4 1 2 3 4 输出示例: 1 8 7 9 0 8 0 9 0 4 思路:题目不难,用大数乘法做之  2.最短时间 给一个有向图,图的各个顶点的

清华大学软件2014机试

清华大学软件2014机试 By 钟桓 9月 24 2014 更新日期:9月 24 2014 今天刚刚机试完,乘者还没忘记,把自己知道的记下来,也算是泽被后来人吧~~~ 这次的机试题,相对来说,会更简单一点,总共3题,时间是3小时. 1 超级幸运数 题目大致描述: 一个数字,若是只含有1和4,这个数字就是幸运数,例如,14,114.但是514这样的就不是了,因为含有其它数字. 若这个幸运数字中,1和4的数量相同,那么就是超级幸运数,例如14,1144,41等等. 题目要求,输入一个n,n的范围是[

华为机试(B)

输入: 字符串只包含小写英文字母, 不考虑非法输入,输入的字符串长度小于等于20个字节. 输出: 删除字符串中出现次数最少的字符后的字符串. 样例输入: abcdd 样例输出: dd #include<iostream> #include<string> #include<iomanip> #include<vector> using namespace std; int main() { string input; getline(cin,input);