2017-03-04 邮票

CJOJ P2221 -【中学高重点内容级本】邮票

本人第一次写博客,有问题请多多海涵

Description

邮局发行一套票面有n(0<n<=10)种不同面值的邮票。若限每封信所贴的邮票张数不得超过m枚,存在整数r使得用不超过m(0<m<=2n)枚的邮票,可以贴出连续整数1,2,3,…,r值来,找出这种面值数,使得r值最大。

Input

一行,输入N及M

Output

输出R

Sample Input

2 3

Sample Output

7

Solution

按照题目的意思,由于要找出最大能拼出的数,因此要用一个函数dp(),来找出最大能拼出的数,然而要找出这个数,还需要找出这n种邮票分别为多少,所以还需要一个函数dfs(),这个函数用来找这n种邮票。
此时,我们可以用一个数组a[x],来储存第x种邮票的面值为多少,同时,用一个数组f[i]表示要凑出总值为i的最少需要的邮票数,a[x]用于找下一个邮票面值,f[i]用于找当前情况下最大能组成的数值,即max(r)。
详细代码(附带每一步的解释)如下:

#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<iostream>
using namespace std;
int n,m,a[100],maxr,f[10000];
void init()
{
  cin>>n>>m;
  a[1]=1;
}
int DP(int n)
{
  int i,j;
  f[0]=0;
  for(i=1;;i++)//枚举总值
    {
      f[i]=-1;//f[i]存要凑出总值为i的最少需要的邮票数
      for(j=1;j<=n;j++)//枚举邮票面值a[j]
    if(i-a[j]>=0/*a[j]可以用来凑i*/ && f[i-a[j]]+1<=m/*加上后邮票数不超过m*/ &&(f[i]==-1 || f[i-a[j]]+1<=f[i])/*可以更新f[i]的值*/)
      f[i]=f[i-a[j]]+1;//更新f[i]的值
      if(f[i]==-1)//凑不出来
    return i-1;//
    }
}
void DFS(int p)
{
  if(p>n)//如果面值大于i,那么就不能再往下dfs,已经到了更新答案的时候了
    {
      int s=DP(n);//n种邮票面值可以凑出的最大值
      if(s>maxr)
    {
      maxr=s;
    }
      return;
    }
  int i;//如果还可以往下深搜
  for(i=a[p-1]+1;i<=DP(p-1)+1;i++)//枚举可以新放的邮票的值,从a[p-1]->目前最大邮票单张面额,dp(p-1)+1->下一张最大单张邮票面额,也就是枚举a[p]可以有的值
    {
      a[p]=i;//更新此时a[p]的值
      DFS(p+1);//对此时已有邮票的单张面额进行深搜,更新a[p+1]的值,或者更新maxr
    }
}

int main()
{

  init();
  DFS(2);
  cout<<maxr<<endl;
}
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 3
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值