题目描述
给定一个信封,最多只允许粘贴NN张邮票,计算在给定KK(N+K≤15N+K≤15)种邮票的情况下(假定所有的邮票数量都足够),如何设计邮票的面值,能得到最大值MAXMAX,使在11至MAXMAX之间的每一个邮资值都能得到。
例如,N=3N=3,K=2K=2,如果面值分别为11分、44分,则在11分~66分之间的每一个邮资值都能得到(当然还有88分、99分和1212分);如果面值分别为11分、33分,则在11分~77分之间的每一个邮资值都能得到。可以验证当N=3N=3,K=2K=2时,77分就是可以得到的连续的邮资最大值,所以MAX=7MAX=7,面值分别为11分、33分。
输入格式
22个整数,代表NN,KK。
输出格式
22行。第一行若干个数字,表示选择的面值,从小到大排序。
第二行,输出“MAX=SMAX=S”,SS表示最大的面值。
输入输出样例
输入 #1复制
3 2
输出 #1复制
1 3 MAX=7
思路
#include <stdio.h>
#include <iostream>
#include <memory.h>
#define inf 2e9+7
using namespace std;
int n,k,s,stamp[21],dp[21*21],maxn(-1),ans[21];
void dfs(int i)
{
register int j;
if(i>k)//如果最大面值超过k
{
int maxx(0);//这个组合的最大面值
memset(dp,0,sizeof(dp));
while(dp[maxx]<=n)//判断邮票值能否为maxx
{
maxx++;
dp[maxx]=inf;
for(j=1;j<=k;j++)
{
if(maxx-stamp[j]<0) break;//如果一张邮票面值大于所求值的话(此时stamp一定单调递增) ,就结束循环
dp[maxx]=min(dp[maxx],dp[maxx-stamp[j]]+1);//dp数组存储达到一个面值所需要的最小的邮票数
}
}
if(maxx-1>maxn)
{
for(j=1;j<=k;j++)
{
ans[j]=stamp[j];
}
maxn=maxx-1;
return;
}
}
else
{
for(j=stamp[i-1]+1;j<=stamp[i-1]*n+1;j++)//一张邮票可以贴m张,因此下一张邮票必须小于上一张*m+1
{
stamp[i]=j;
dfs(i+1);
}
}
}
signed main()
{
ios::sync_with_stdio(false);
cin.tie(0);
cout.tie(0);
register int i;
cin>>n>>k;
stamp[1]=1;
dfs(2);
for(i=1;i<=k;i++)
{
cout<<ans[i]<<' ';
}cout<<endl;
cout<<"MAX="<<maxn<<endl;
return 0;
}