2337 - 邮票面值设计
时间限制 : 1 秒
内存限制 : 125 MB
给定一个信封,最多只允许粘贴N张邮票,计算在给定K(N+K≤40)种邮票的情况下(假定所有的邮票数量都足够),如何设计邮票的面值,能得到最大值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分。
<br />
题目输入
每个测试文件只包含一组测试数据,每组输入两个整数N和K(N+K≤40)。
题目输出
对于每组输入数据,第一行输出每种邮票的面值,面值之间由一个空格分隔,最后一个面值的后面不要输出空格。第二行输出连续最大能到的面值数,具体格式见样例输出。数据保证答案唯一。
输入/输出样例
输入格式
3 2
输出格式
1 3 MAX=7
C++解答
#include<cstdio> #include<cstring> #include<algorithm> using namespace std; const int maxn1=40; const int maxn2=10000; int n,m,ans=0,f[maxn1][maxn2]; int a[maxn1+20],b[maxn2+20]; void dfs(int step,int s,int e) { int i,j,k; if(step>m) { if(ans<e-1)for(ans=e-1,i=1;i<=m;i++)b[i]=a[i]; return; } for(k=e;k>=s;k--) { j=a[step-1]*n; for(i=0;i<=j;i++)f[step][i]=f[step-1][i]; memset(&f[step][j+1],25,sizeof(int)*((n*k+1-j)+10)); for(j=n*k,i=k;i<=j;i++) f[step][i]=min(f[step][i],f[step][i-k]+1); for(i=e;i<=j+1;i++)if(f[step][i]>n) { a[step]=k,dfs(step+1,k+1,i); break; } } } int main() { int i; memset(f[1],25,sizeof(f[1])); scanf("%d%d",&n,&m); for(i=0;i<=n;i++)f[1][i]=i; a[1]=1,dfs(2,2,n+1); for(i=1;i<m;i++)printf("%d ",b[i]); printf("%d\nMAX=%d\n",b[m],ans); return 0; }