蓝桥杯 排列数(DFS搜索)

 算法提高 排列数  
时间限制:1.0s   内存限制:256.0MB
    
问题描述
  0、1、2三个数字的全排列有六种,按照字母序排列如下:
  012、021、102、120、201、210
  输入一个数n
  求0~9十个数的全排列中的第n个(第1个为0123456789)。
输入格式
  一行,包含一个整数n
输出格式
  一行,包含一组10个数字的全排列
样例输入
1
样例输出
0123456789
数据规模和约定
  0 < n <= 10!


觉得蓝桥杯练习系统比较坑爹的地方就在于这道题用提示所说的枚举、循环根本行不通,一开始写好了这样暴力的代码,结果根本无法运行。暴力代码如下:
#include<stdio.h>
int main()
{
    int a1,a2,a3,a4,a5,a6,a7,a8,a9,a0,sum=0,flag=0;
    long long n;
    scanf("%d",&n);
    for(a0=0; a0<=9; a0++)
    {
        for(a1=0; a1<=9; a1++)
        {
            if(a0==a1)
                continue;
            for(a2=0; a2<=9; a2++)
            {
                if(a2==a0||a2==a1)
                    continue;
                for(a3=0; a3<=9; a3++)
                {
                    if(a3==a0||a3==a1||a3==a2)
                        continue;
                    for(a4=0; a4<=9; a4++)
                    {
                        if(a4==a0||a4==a1||a4==a2||a4==a3)
                            continue;
                        for(a5=0; a5<=9; a5++)
                        {
                            if(a5==a0||a5==a1||a5==a2||a5==a3||a5==a4)
                                continue;
                            for(a6=0; a6<=9; a6++)
                            {
                                if(a6==a0||a6==a1||a6==a2||a6==a3||a6==a4||a6==a5)
                                    continue;
                                for(a7=0; a7<=9; a7++)
                                {
                                    if(a7==a0||a7==a1||a7==a2||a7==a3||a7==a4||a7==a5||a7==a6)
                                        continue;
                                    for(a8=0; a8<=9; a8++)
                                    {
                                        if(a8==a0||a8==a1||a8==a2||a8==a3||a8==a4||a8==a5||a8==a6||a8==a7)
                                            continue;
                                        for(a9=0; a9<=9; a9++)
                                        {
                                            if(a9==a0||a9==a1||a9==a2||a9==a3||a9==a4||a9==a5||a9==a6||a9==a7||a9==a8)
                                                continue;
                                            sum++;
                                            if(sum==n)
                                            {
                                                printf("%d%d%d%d%d%d%d%d%d%d\n",a0,a1,a2,a3,a4,a5,a6,a7,a8,a9);
                                                flag=1;
                                                break;
                                            }
                                        }
                                        if(flag)
                                            break;
                                    }
                                    if(flag)
                                        break;
                                }
                                if(flag)
                                    break;
                            }
                            if(flag)
                                break;
                        }
                        if(flag)
                            break;
                    }
                    if(flag)
                        break;
                }
                if(flag)
                    break;
            }
            if(flag)
                break;
        }
        if(flag)
            break;
    }
    return 0;
}

这个题的正确解法应该是DFS搜索,简单明了。代码如下
#include<stdio.h>
#include<string.h>
long long n,sum;
int vis[10];//用来标记数字i是否被用了,即是否已被放在了排列中
int a[10];
void dfs(int pos)
{
    if(pos==10)//表示当前数组a中已有10个数字
    {
        sum++;
        if(sum==n)
        {
            for(int i=0; i<10; i++)
                printf("%d",a[i]);
            printf("\n");
        }
    }
    for(int i=0; i<=9; i++)//枚举数字0到数字9
    {
        if(!vis[i])//若数字i还没被放在当前排列中
        {
            a[pos]=i;//将i赋给当前排列a数组的第pos位置
            vis[i]=1;//数字i已放入排列中,标记为1
            dfs(pos+1);//继续搜索下一个位置
            vis[i]=0;//清除标记
        }
    }
}
int main()
{
    while(~scanf("%lld",&n))
    {
        memset(vis,0,sizeof(vis));
        sum=0;
        dfs(0);
    }
    return 0;
}



  • 6
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 12
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值