题目描述
给定一个信封,最多只允许粘贴 张邮票,计算在给定 ( )种邮票的情况下(假定所有的邮票数量都足够),如何设计邮票的面值,能得到最大值 ,使在 至 之间的每一个邮资值都能得到。
例如, , ,如果面值分别为 分、 分,则在 分~ 分之间的每一个邮资值都能得到(当然还有 分、 分和 分);如果面值分别为 分、 分,则在 分~ 分之间的每一个邮资值都能得到。可以验证当 , 时, 分就是可以得到的连续的邮资最大值,所以 ,面值分别为 分、 分。
输入格式
个整数,代表 , 。
输出格式
行。第一行若干个数字,表示选择的面值,从小到大排序。
第二行,输出“ ”, 表示最大的面值。
输入输出样例
输入 #1 复制
3 2
输出 #1 复制
1 3
MAX=7
思路
动态规划,用
表示拼成
最少需要多少张邮票。
转移公式:
再来一个
就可以了。
(加上一个回溯)
代码
#include<bits/stdc++.h>
using namespace std;
int n,m;
int a[21];
int maxx=0,ans[21];
int f[51000];
int dp(int k){
memset(f,63,sizeof(f));//附一个较大的值
f[0]=0;
for(int i=1;i<=k;i++)
for(int j=a[i];j<=a[k]*n;j++)
if(f[j-a[i]]<n)
f[j]=min(f[j],f[j-a[i]]+1);
int x=0;
while(f[x+1]<=100)
x++;
return x;
}
void dfs(int k){
if(k==m+1){
int t=dp(k-1);
if(t>maxx){
maxx=t;
memcpy(ans,a,sizeof(ans));
}
return;
}
int end=dp(k-1);
for(int j=a[k-1]+1;j<=end+1;j++){
a[k]=j;
dfs(k+1);
a[k]=0;
}
}
int main(){
cin>>n>>m;
a[1]=1;
dfs(2);
for(int i=1;i<=m;i++)
printf("%d ",ans[i]);
printf("\nMAX=%d\n",maxx);
return 0;
}