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

    题目描述

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

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

    输入输出格式

    输入格式:

     

    2个整数,代表N,K。

     

    输出格式:

     

    2行。第一行若干个数字,表示选择的面值,从小到大排序。

    第二行,输出“MAX=S”,S表示最大的面值。

     

    输入输出样例

    输入样例#1:
    3 2
    
    输出样例#1:
    1 3
    MAX=7
     1 #include <iostream>
     2 #include <string>
     3 #include <cstdio>
     4 #include <algorithm>
     5 #include <stdlib.h>
     6 
     7 using namespace std;
     8 const int maxn=20;
     9 int n,k;//张数 面值数
    10 int maxx=0,kind[maxn],res[maxn];
    11 
    12 int dp(int t){
    13     //初始化f[]
    14     int f[5000]={0};//达到连续到某数时需要的最小张数
    15     for(int i=1;i<=kind[t]*n;i++)
    16         f[i]=9999;
    17     for(int i=1;i<=t;i++)
    18         for(int j=kind[i];j<=kind[t]*n;j++){
    19             f[j]=min(f[j],f[j-kind[i]]+1);
    20         }
    21     for(int i=1;i<=kind[t]*n;i++){
    22         if(f[i]>n)
    23             return i-1;
    24     }
    25     return kind[t]*n;
    26 }
    27 
    28 void dfs(int t,int maxnum){//第几张面值 目前可以连续到多少
    29     if(t==k+1)
    30        {
    31         if(maxnum>maxx)
    32         {
    33             maxx=maxnum;
    34             for(int i=1;i<=k;i++)
    35                 res[i]=kind[i];
    36         }
    37         return;
    38     }
    39     for(int i=kind[t-1]+1;i<=maxnum+1;i++)
    40     {
    41         kind[t]=i;
    42         int _maxnum=dp(t);
    43         dfs(t+1,_maxnum);
    44     }
    45 }
    46 
    47 int main()
    48 {
    49     scanf("%d%d",&n,&k);
    50     dfs(1,0);
    51     printf("%d",res[1]);
    52     for(int i=2;i<=k;i++)
    53         printf(" %d",res[i]);
    54     printf("
    MAX=%d
    ",maxx);
    55     return 0;
    56 }
    View Code

    dp+dfs

    解释: dfs(t,maxnum) 表示搜索到了第 t 张面值选择,而前 t+1 张能够最多连续取值 1~maxnum 

     dp(t) 返回在某次搜索中,此时 t 张面值能够最多连续取值的最大值

    面值是递增存放的

    思路:

    dp:状态转移: f[x]=min(f[x],f[x-kind[i]]+1) 其中f数组中存储的是在这次搜索中,t张面值的纸币来取到x最小需要几张

    在每次一点点将每张面值加进去的时候(即17行dp函数外层循环),由于x(在这张面值加入进去能够取到的数)最小为这张面值,最大为 kind[t]*n (即最大面值有最大张数时),所以内层循环的边界是这样写的

    dfs比较清楚

    最近不是很想干正事~昨天不然应该写完的,但是后来还是打了一晚上游戏(*・ω-q) 

    所以虽然难度标的是普及,但当时根本没心思写所以感觉超难……

    注定失败的战争,也要拼尽全力去打赢它; 就算输,也要输得足够漂亮。
  • 相关阅读:
    第12章,存储类别、链接和内存管理
    第11章 字符串和字符串函数
    第10章 数组和指针
    第9章 函数
    第8章 字符输入/输出和输入验证
    第7章,c语言控制语句:分支和跳转
    第六章,处语言控制语句:循环
    中国互联网发展史
    世界互联网发展史
    世界计算机发展史
  • 原文地址:https://www.cnblogs.com/yalphait/p/8761824.html
Copyright © 2011-2022 走看看