算法提高 邮票面值设计
时间限制:1.0s 内存限制:256.0MB
问题描述
给定一个信封,最多只允许粘贴N张邮票,计算在给定K(N+K≤13)种邮票的情况下(假定所有的邮票数量都足够),如何设计邮票的面值,能得到最大值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分。
输入格式
一行,两个数N、K
输出格式
两行,第一行升序输出设计的邮票面值,第二行输出“MAX=xx”(不含引号),其中xx为所求的能得到的连续邮资最大值。
样例输入
3 2
样例输出
1 3
MAX=7
具体看得不是太明白,在别人的代码里面加了一点自己的理解,留到以后水平够了再更新
#include<iostream>
#define N 50
using namespace std;
#define inf 500
#include<cstdio>
#include<cstring>
int b[N],ans=0,a[N],f[inf];//a[N]用来记录邮票的面值
int n,k;void dfs(int m)//搜索第m种的情况
{memset(f,0x3f,sizeof(f));//用 f[i] 记录达到数值 i 所需的最小邮票数量,初始化为一个极大值。 f[0]=0;//当所有的邮票加起来数值为零时不需要邮票 int i;for(i=1;i<=inf;i++)//i是总面值 {for(int j=1;j<=m&&a[j]<=i;j++)//··邮票的种数和面值进行控制···邮票面值小于总面值 f[i]=min(f[i],f[i-a[j]]+1);if(f[i]>n)//如果邮票贴满了 {i--;//回到上一次循环,i的值, if(i>ans)//更新ans的值 {ans=i;for(int l=1;l<=m;l++)//记录下来当前取得最优解时前m个邮票的面额 b[l]=a[l]; }break;}}if(m==k)return;//如果当前搜索到的邮票的种数等于给定的数目,搜索中回溯, for(int j=i+1;j>a[m];j--){a[m+1]=j;//搜索的下一种邮票面额从很大的值到比上一个大,dfs(m+1);//继续搜索下一个 }
}int main()
{cin>>n>>k;a[1]=1;dfs(1);//从就一种邮票开始搜 for(int i=1;i<=k;i++)//输出K种面额 cout<<b[i]<<" ";cout<<endl;cout<<"MAX="<<ans<<endl;}