《算法竞赛进阶指南》-AcWing-92. 递归实现指数型-题解

Posted Tisfy

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了《算法竞赛进阶指南》-AcWing-92. 递归实现指数型-题解相关的知识,希望对你有一定的参考价值。

递归实现指数型枚举

传送门

问题描述

给你一个正整数 n ( 1 ≤ n ≤ 20 ) n(1\\leq n\\leq20) n(1n20),从中选取任意多个数,打印所有选法。

对于每种选法,从小到大输出所选的数。

样例输入

3

样例输出


3
2
2 3
1
1 3
1 2
1 2 3

这道题有特判,只需要输出了每组测试数据、每组数据中的数是从小到大的即可。

解题思路

这里介绍两种方法:一种正如题面所说,用递归实现;另一种借助前面介绍的求二进制状态下哪几位是1的方法通过状态压缩来实现。

方法一

每个数都能选与不选。定义一个vector来记录选择了哪些元素;定义一个函数calu(int x)表示该处理第x个元素了。

当x>n时,说明已经处理完n个元素了,就之间打印。

否则,分别对 选 与 不选 第x个元素进行递归,若选就push到vector中,不选就不push。记得递归结束pop出来保留现场。

#include <bits/stdc++.h>
using namespace std;
#define mem(a) memset(a, 0, sizeof(a))
#define dbg(x) cout << #x << " = " << x << endl
#define fi(i, l, r) for (int i = l; i < r; i++)
#define cd(a) scanf("%d", &a)
typedef long long ll;
vector<int>v;
int n;
void prt()
{
    for(int i=0;i<v.size();i++)
        printf("%d ",v[i]);
    puts("");
}
void calu(int x)
{
    if(x>n)
        return prt();
    calu(x+1);
    v.push_back(x);
    calu(x+1);
    v.pop_back();
}
int main()
{
    cin>>n;
    calu(1);
    return 0;
}

方法二

用0~2n这2n个数代表每个元素的选与不选。每个数代表一种状态。对于一个状态数x,x的第j位若为0就代表不选元素j+1,否则为1代表选择元素j+1。

为了提高效率,可以使用前面介绍的通过lowbit来快速提取一个数中所有为1的位的方法进行优化。

#include <bits/stdc++.h>
using namespace std;
#define mem(a) memset(a, 0, sizeof(a))
#define dbg(x) cout << #x << " = " << x << endl
#define fi(i, l, r) for (int i = l; i < r; i++)
#define cd(a) scanf("%d", &a)
typedef long long ll;
int H[37];
void init()
{
    for(int i=0;i<36;i++)
        H[(1ll<<i)%37]=i;
}
void prt(int n)
{
    while(n)
    {
        printf("%d ",H[(n&-n)%37]+1);
        n-=n&-n;
    }
    puts("");
}
int main()
{
    init();
    int n;
    cin>>n;
    for(int i=0;i<1<<n;i++)
        prt(i);
    return 0;
}

当然也可以不使用那么高效的方法而是直接取出一个状态数的每一位。

#include <bits/stdc++.h>
using namespace std;
#define mem(a) memset(a, 0, sizeof(a))
#define dbg(x) cout << #x << " = " << x << endl
#define fi(i, l, r) for (int i = l; i < r; i++)
#define cd(a) scanf("%d", &a)
typedef long long ll;
int n;
void prt(int x)
{
    for(int i=0;i<n;i++)
        if(x>>i&1)
            printf("%d ",i+1);
    puts("");
}
int main()
{
    cin>>n;
    for(int i=0;i<1<<n;i++)
        prt(i);
    return 0;
}

原创不易,转载请附上原文链接哦~
Tisfy:https://letmefly.blog.csdn.net/article/details/119252103

以上是关于《算法竞赛进阶指南》-AcWing-92. 递归实现指数型-题解的主要内容,如果未能解决你的问题,请参考以下文章

算法竞赛进阶指南基本算法:递推与递归

《算法竞赛进阶指南》-AcWing-94. 递归实现排列型枚举-题解

《算法竞赛进阶指南》-AcWing-94. 递归实现排列型枚举-题解

《算法竞赛进阶指南》-AcWing-93. 递归实现组合型枚举-题解

《算法竞赛进阶指南》-AcWing-93. 递归实现组合型枚举-题解

算法竞赛进阶指南做题记录