zoukankan      html  css  js  c++  java
  • noip 邮票面值设计

    描述

    给定一个信封,最多只允许粘贴N张邮票,计算在给定M(N+M<=10)种邮票的情况下(假定所有的邮票数量都足够),如何设计邮票的面值,能得到最大max ,使得1~max之间的每一个邮资值都能得到。

    例如,N=3,M=2,如果面值分别为1分、4分,则在l分~6分之间的每一个邮资值都能得到(当然还有8分、9分和12分):如果面值分别为1分、3分,则在1分~7分之间的每一个邮资值都能得到。可以验证当N=3,M=2时,7分就是可以得到连续的邮资最大值,所以MAX=7,面值分别为l分、3分。

    样例输入:共一行,两个整数,分表为N与M的值。

    格式

    输入格式

    一行,分别为N,M。

    输出格式

    两行。

    第一行为m种邮票的面值,按升序排列,各数之间用一个空格隔开。

    第二行为最大值。

    如果有多解,输出字典序最大的一个。

    样例1

    样例输入1[复制]

     
    3 2

    样例输出1[复制]

     
    1 3
    MAX=7

    限制

    各个测试点1s

    来源

    NOIP1999

    (转自https://vijos.org/p/1179)


      这道题首先看数据范围就大概能够猜出是搜索,可是,出现了以下问题

      1)搜索的范围,不可能从1搜到1000

      2)如何求MAX

      先来思考问题二,首先回顾一下求出面值为i所需最少的邮票怎么求,用动规对不对?

    f[i] = min(f[i - 面额] + 1, f[i]),这样求的对不对?

      那从1一直往下做,求到某个f[i] > n,说明什么?i这个面值不能用要超过n张的邮票

    凑出来,故MAX = i - 1

      问题二解决了,然后来解决问题一,首先上限,很容易想到,当前的MAX + 1,为什么

    不能是MAX + 2,或者更多,因为MAX + 1就凑不出来了。然后来思考下限,前一个面额 + 1?

    如果比它少会发生什么?MAX貌似不会改变。所以得到了这个范围[前一个面额 + 1, 当前MAX]

      接下来附上代码

    Code

     1 /**
     2  * vijos.org
     3  * Problem#1179
     4  * Accepted
     5  * Time:107ms
     6  * Memory:568k
     7  */
     8 #include<iostream>
     9 #include<cstring>
    10 #include<cstdio>
    11 #include<cstdlib>
    12 using namespace std;
    13 int buf[45];
    14 int ans[45];
    15 int f[1001];
    16 int n ,k;
    17 int maxv = 0;
    18 int cale(int count){
    19     if(!count)    return 0;
    20     memset(f, 0x7f, sizeof(f));
    21     f[0] = 0;
    22     int i = 1;
    23     do{
    24         for(int j = 1;j <= count && buf[j] <= i;j++)
    25             f[i] = min(f[i - buf[j]] + 1, f[i]);
    26     }while(f[i++] <= n);
    27     return i - 2;
    28 }
    29 void search(int sec){
    30     if(sec >= k){
    31         int c = cale(k);
    32         if(c <= maxv)    return;
    33         for(int i = 1;i <= k; i++)
    34             ans[i] = buf[i];
    35         maxv = c;
    36         return;
    37     }else{
    38         int temp = cale(sec);
    39         for(int i = temp + 1;i > buf[sec]; i--){
    40             buf[sec + 1] = i;
    41             search(sec + 1);
    42         }
    43     }
    44 }
    45 int main(){
    46     cin >> n >> k;
    47     search(0);
    48     for(int i = 1;i <= k;i++)
    49         cout<<ans[i]<<" ";
    50     cout<<endl;
    51     cout<<"MAX="<<maxv;
    52     return 0;
    53 }
  • 相关阅读:
    Java数据结构与算法之---求两个数的最大公约数(欧几里得算法)
    Linux下面配置文件~/.bash_profile
    Java数据结构之回溯算法的递归应用迷宫的路径问题
    Java数据结构之对称矩阵的压缩算法---
    Java数据结构之字符串模式匹配算法---KMP算法2
    Java数据结构之字符串模式匹配算法---KMP算法
    Java数据结构之字符串模式匹配算法---Brute-Force算法
    Java数据结构之表的增删对比---ArrayList与LinkedList之一
    Java数据结构之队列的实现以及队列的应用之----简单生产者消费者应用
    Java堆栈的应用1----------堆栈的自定义实现以及括号匹配算法的Java实现
  • 原文地址:https://www.cnblogs.com/yyf0309/p/5814725.html
Copyright © 2011-2022 走看看