一. 题目

image.png

二. 理论

  • 规定每一行升序去选, 保证去除冗余同时字典序最小

  • 若已选的加上剩余可选的不足m直接剪枝即可

三. 代码

#include <iostream>
#include <algorithm>
using namespace std;
const int N=30;

int n, m;

class Search
{
public:
    int path[N];//存储选择方案
public:
    void initIO()
    {
        // 关闭输入输出缓存,使效率提升
        ios::sync_with_stdio(false);
        // 解除cin和cout的默认绑定,来降低IO的负担使效率提升
        cin.tie(nullptr);
        cout.tie(nullptr);
    }

    Search()
    {
        initIO();
        fill(path, path+N, 0);
    }

    /**
     * 搜索函数
     * @param u 表示选了几个
     * @param st 每层开始选的起点,保证字典序,同时排除重复选法(不考虑顺序)
     */
    void dfs(int u, int st)
    {
        //选了u个+上剩余可选的不足m时, 直接结束递归
        if(u+n-st+1<m) return;
        if(u==m)//选够m个
        {
            for(int i=0;i<m;++i)
                cout<<path[i]<<" ";
            cout<<endl;
            return;
        }

        for(int i=st;i<=n;++i)
        {
            path[u]=i;
            dfs(u+1, i+1);
        }
    }
}s;

int main()
{
    cin>>n>>m;
    s.dfs(0, 1);//最开始可选m个数
}