指数型枚举

 

从 1~n 这 n 个整数中随机选取任意多个,输出所有可能的选择方案。

输入格式

输入一个整数n。

输出格式

每行输出一种方案。

同一行内的数必须升序排列,相邻两个数用恰好1个空格隔开。

对于没有选任何数的方案,输出空行。

本题有自定义校验器(SPJ),各行(不同方案)之间的顺序任意。

数据范围

1≤n≤151≤n≤15

输入样例:

3

输出样例:


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

题意是这样的,首先看一眼题目,知道这题必然是搜索也就是递归,那么怎么做呢,首先我们最重要的要一定要确定好搜索的状态,一个状态是当前最大的数m,另一个状态是当前搜索了几个数字,最后一个状态是需要搜索几个数字。

假如只搜索一个数字的话,我们的递归函数可以这样写。

int dfs(int m,int now,1)
{
}

接下来,我们需要确定好边界条件。

   
int dfs(int m,int now,1)
{
 if(now==1)//边界条件
    {
        for(int i=1;i<=n;i++)//n是总共多少个数
        {
            if(visit[i])//遍历标记数组,找到已经存在的数字
            {
                cout<<i<<" ";
            }
        }
        cout<<endl;
        return 1;
    }
}

接下来我们需要写递归函数

int dfs(int m,int now,1)
{
    if(now==1)//边界条件
    {
        for(int i=1;i<=n;i++)
        {
            if(visit[i])
            {
                cout<<i<<" ";
            }
        }
        cout<<endl;
        return 1;
    }
    for(int i=m+1;i<=n;i++)//要注意m是这一层最大的数,不然的话很出现很多重复不需要的数字
    {
        if(!visit[i])
        {
            visit[i]=1;
            dfs(i,now+1,goal);//往下回溯
            visit[i]=0;
//            dfs(i,now,goal);
//            return 1;
        }
    }
}

就这样,搜索一个数的递归函数就写完了。很多地方我没细说,看上一篇递归题里面比较详细。

那么搜索n个数的递归函数其实就是在主函数里写个for循环。

下面是程序的全部代码:

#include <iostream>
#include <cstring>
using namespace std;

const int M=1000;
int n;
int visit[M];
int dfs(int m,int now,int goal)
{
    if(now==goal)
    {
        for(int i=1;i<=n;i++)
        {
            if(visit[i])
            {
                cout<<i<<" ";
            }
        }
        cout<<endl;
        return 1;
    }
    for(int i=1;i<=n;i++)
    {
        if(!visit[i])
        {
            visit[i]=1;
            dfs(i,now+1,goal);
            visit[i]=0;
//            dfs(i,now,goal);
//            return 1;
        }
    }
}
int main()
{
    cin>>n;
    cout<<endl;
    for(int i=1;i<=n;i++)
    {
        memset(visit,0,sizeof(visit));
        dfs(0,0,i);
    }
    return 0;
}

当然还有一种做法,不过不推荐。————————————可以不看————————————————————————

#include <iostream>
#include <algorithm>
#include <stack>
#include <cstdio>
#include <cstdlib>
#include <cstring>
using namespace std;

const int M=1000;
int a[M],a_copy[M],m,book[M],record[M][M],k;

bool isre(int *a,int num)
{
    int ok=1;
    for(int i=0; i<=M; i++)
    {
        ok=1;
        for(int j=1; j<=num; j++)
        {
            if(a[j]!=record[i][j])
            {
                ok=0;
            }
        }
        if(ok)return true;
    }
    return false;
}
bool re(int *a,int num)
{
    int ok=0;
   for(int i=1;i<=num;i++)
   {
       ok=0;
       for(int j=1;j<=num;j++)
       {
           if(a[i]==a[j])
           {
               ok++;
               if(ok==2)return true;
           }
       }
   }
    return false;
}
void dfs(int n,int num)
{
    if(n==m+1)
    {
        for(int i=1; i<=num; i++)a_copy[i]=a[i];
        sort(a_copy+1,a_copy+num+1);
        for(int j=1; j<=m; j++)
        {
            sort(a_copy+1,a_copy+m+1);
            if(!isre(a_copy,j)&&!re(a_copy,j))
            {
                for(int i=1; i<=j; i++)
                {
                    cout<<a_copy[i]<<" ";
                }
                for(int i=1; i<=j; i++)
                {
                    record[k][i]=a_copy[i];
                }
                k++;
                cout<<endl;
            }
        }
        return;
    }
    for(int i=1; i<=m; i++)
    {
        if(!book[i])
        {
            book[i]=1;
            a[i]=n;
            dfs(n+1,i);
            book[i]=0;
        }
    }
}
int main()
{
    while(cin>>m)
    {
       dfs(1,1);
       memset(a,0,sizeof(int)*M);
       memset(book,0,sizeof(int)*M);
       memset(a_copy,0,sizeof(int)*M);
       memset(record,0,sizeof(int)*M*M);
    }
    return 0;
}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值