import java.util.Scanner;
public class Main {
    private static int[] a;
    private static int n;
    private static int k;
    private static int max = 0;
    private static int[] b = new int[100];
    public static void main(String[] args) {
        Scanner input = new Scanner(System.in);
        n = input.nextInt();
        k = input.nextInt();
        a = new int[40]; //存可能的面值
        a[0] = 1; //必须有面值1
        dfs(1); //开始搜索,从第二个面值开始枚举
        for (int i = 0; i < k; i++) {
            System.out.print(b[i] + " ");
        }
        System.out.println("\nMAX=" + max);
    }
    private static void dfs(int i) {
        if (i == k) { //举例完k种
            chexk();
        } else {
            for (int j = a[i - 1] + 1; j <= ((a[i - 1] * n) + 1); j++) { //下一个面值一定在上一个面值+1到上一个面值*最多贴的张数+1之间
                a[i] = j;
                dfs(i + 1);
            }
        }
    }
    private static void chexk() { //动态规划求最大值
        int[] dp = new int[1000]; //最大连续尽量大一点,避免越界。下标i表示当前邮资,dp[i]表示所需最少张数
        dp[0] = 0; //邮资为零时一定是零张
        int i = 0;
        while (dp[i] <= n) { //当最少张数大于最多可贴张数时跳出
            i++;
            dp[i] = 99999; //假设当前邮资下需要贴99999张邮票
            for (int j = 0; (j < k) && (a[j] <= i); j++) { //寻找所有的邮票,且这张邮票的面值不大于当前的邮资
                if ((dp[i - a[j]] + 1) < dp[i]) { //当前邮资减去这张邮票面值张数加一如果小于当前邮资现用组合张数,则替换
                    dp[i] = dp[i - a[j]] + 1;
                }
            }
        }
        if ((i - 1) > max) {
            max = i - 1;
            for (int j = 0; j < k; j++) {
                b[j] = a[j];
            }
        }
    }
}


点赞(0)
 

0.0分

4 人评分

C语言网提供由在职研发工程师或ACM蓝桥杯竞赛优秀选手录制的视频教程,并配有习题和答疑,点击了解:

一点编程也不会写的:零基础C语言学练课程

解决困扰你多年的C语言疑难杂症特性的C语言进阶课程

从零到写出一个爬虫的Python编程课程

只会语法写不出代码?手把手带你写100个编程真题的编程百练课程

信息学奥赛或C++选手的 必学C++课程

蓝桥杯ACM、信息学奥赛的必学课程:算法竞赛课入门课程

手把手讲解近五年真题的蓝桥杯辅导课程

评论列表 共有 2 条评论

MK 5年前 回复TA
那个,给个建议哈,作者可以把代码格式搞好点,加上缩进,我们这些读者会看得舒服点
小哈哈 6年前 回复TA
太棒了,大神啊,66666666666666666666,我把你的代码在纸上抄了几遍才懂,赫然间惊为天人