P1706 全排列问题 题解(DFS,位运算)

全排列问题

题目描述

按照字典序输出自然数 1 1 1 n n n 所有不重复的排列,即 n n n 的全排列,要求所产生的任一数字序列中不允许出现重复的数字。

输入格式

一个整数 n n n

输出格式

1 ∼ n 1 \sim n 1n 组成的所有不重复的数字序列,每行一个序列。

每个数字保留 5 5 5 个场宽。

样例 #1

样例输入 #1

3

样例输出 #1

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

提示

1 ≤ n ≤ 9 1 \leq n \leq 9 1n9

思路

这道题很简单,一道 普及 − 普及- 普及难度的题。没有什么可以讲得,就是一个简单地一个 D F S DFS DFS的暴力搜索。这道题暴力是可以Ac的,但是如果你想(抢最优解 ) 优化,优化起来的过程还是很难的。

第一种解法(较慢, 66 m s 66ms 66ms

直接暴力搜索,放心,真的不会 T L E TLE TLE。最高也才只有 47 m s 47ms 47ms在这里插入图片描述

C o d e 1 Code1 Code1
#include<bits/stdc++.h>

using namespace std;
const int N=100+5;
int n;
bool vis[N];
int used[N]; 
void out(){
    for(int i=0;i<n;i++){
        printf("%5d", used[i]);
    }
    cout<<endl;
    return ;
}
void dfs(int x){
    if(x==n){
        out();
        return ;
    }
    for(int i=1;i<=n;i++){
        if(!vis[i]){
            vis[i]=1;
            used[x]=i;
            dfs(x+1);
            vis[i]=0;
        }
    }
}
int main(){

    scanf("%d",&n);
    dfs(0);
    return 0;
}

第二种解法(很快,37 m s ms ms

优化思路:通过 l o w b i t ( x ) lowbit(x) lowbit(x) log ⁡ 2 x \log_2 x log2x来直接快速定位x中的二进制1,加速寻找没有选择的数字。

C o d e 2 Code2 Code2
#include <bits/stdc++.h>

using namespace std;
int n;
int rk[10];
int Log[1030];
int all;
int lowbit(int x){
    return x&(-x);
}
void dfs(int state,int d){
    if(n==d){
        for(int i=1;i<=n;i++){
            printf("%5d",rk[i]);
        }
        printf("\n");
        return ;
    }
    //翻转状态
    //使用lowbit进行加速   取反~
    int vis=all&(~state);
    while(vis){
        int x=lowbit(vis);
        rk[d+1]=Log[x]+1;
        dfs(state|x,d+1);
        vis-=x;
    }
}
int main(){

    scanf("%d",&n);
    all=(1<<n)-1;
    for(int i=2;i<=all;i++){
        Log[i]=Log[i/2]+1;
    }
    dfs(0,0);
    return 0;
}

严禁抄袭!!!

  • 2
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值