1 /*
2 这个题目知道是深搜,但是邮票面值的上界在深搜中不好确定,只知道下界是>前一个,这里就妙在用DP解决了深搜的上界,和当前邮票可以取到的连续最大值
3 */
4 /*
5 ①搜索。对每一步,枚举邮票面值,然后搜索下一张邮票面值并更新最优解。
6
7 ②完全背包确定搜索范围。
8
9 假设现在枚举到第 i 张邮票面值,第 i-1 张邮票面值为a[i-1],前 i-1 张邮票得到的最大连续值为x,则第 i 张邮票面值的范围就为 [a[i-1]+1,x+1];
10
11 假设现在有 n 张邮票,怎么得到其最大连续值呢?
12
13 用 f[i] 记录达到数值 i 所需的最小邮票数量,初始化为一个极大值。然后用完全背包算出 f[i] 的值,从 0 开始,第一个f[i]>n,则 i-1 就为最大连续值。
14
15 */
16 #define N 50
17 #include<iostream>
18 using namespace std;
19 #define inf 500
20 #include<cstdio>
21 #include<cstring>
22 int b[N],ans=0,a[N],f[inf];
23 int n,k;
24 void dfs(int m)
25 {
26 memset(f,0x3f,sizeof(f));
27 f[0]=0;
28 int i;
29 for(i=1;i<=inf;++i)
30 {
31 for(int j=1;j<=m&&a[j]<=i;++j)
32 f[i]=min(f[i],f[i-a[j]]+1);/*完全背包是可以把物品空间的内外循环交换位置的,反正都是无限放*/
33 if(f[i]>n)/*当前m种邮票所能取到的最大值*/
34 {
35 i--;
36 if(i>ans)
37 {
38 ans=i;
39 for(int l=1;l<=m;++l)
40 b[l]=a[l];
41 }
42 break;
43 }
44 }
45
46 if(m==k) return;
47 for(int j=i+1;j>a[m];--j)
48 {/*下一张邮票的范围*/
49 a[m+1]=j;
50 dfs(m+1);
51 }
52 }
53 int main()
54 {
55 scanf("%d%d",&n,&k);
56 a[1]=1;
57 dfs(1);
58 for(int i=1;i<=k;++i)
59 printf("%d ",b[i]);
60 printf("\n");
61 printf("MAX=%d\n",ans);
62 return 0;
63 }