【第十五届蓝桥杯备赛(bushi,写文凑个数)】蓝桥OJ---排列序数

文章目录

  • 一、题目
    • 1、原题链接
    • 2、题目描述
  • 二、解题报告
    • 1、思路分析
    • 2、时间复杂度
    • 3、代码详解
  • 三、知识风暴
  • DFS

一、题目

1、原题链接

排列序数

2、题目描述

如果用 a b c d 这 4 个字母组成一个串,有 4!=24 种,如果把它们排个序,每个串都对应一个序号:

abcd 0

abdc 1

acbd 2

acdb 3

adbc 4

adcb 5

bacd 6

badc 7

bcad 8

bcda 9

bdac 10

bdca 11

cabd 12

cadb 13

cbad 14

cbda 15

cdab 16

cdba 17

⋯ ⋯
现在有不多于 10 个两两不同的小写字母,给出它们组成的串,你能求出该串在所有排列中的序号吗?
输入描述
输入一行,一个串。

输出描述

输出一行,一个整数,表示该串在其字母所有排列生成的串中的序号。注意:最小的序号是 0。

输入输出样例

输入

bdca

输出

11

二、解题报告

1、思路分析

(1)DFS搜索即可,和全排列数思路一样。
(2)至于序号,与我们搜索到的方案数顺序正好相同,直接将每次搜索到的方案数编号,当时第一思路是将每种方案和其编号记录到哈希表中,之后再进行查找,但是有几个数据超时了(时间复杂度最坏10*10!,超过计算机1s计算量)。可以直接搜到输入的方案直接输出,结束程序即可。

2、时间复杂度

时间复杂度O(n*n!)

3、代码详解

#include 
#include 
using namespace std;
const int N=15;
bool st[N];
string s;
int idx,len;
//DFS搜索,和全排列数的搜索方式相同,只不过参数成了字符串
void dfs(int u,string path){
  //如果找到一组方案
  if(u==len){
     //判断是否和输入的字符串相同
     if(path==s){
         cout<<idx;   //如果相同,直接输出其编号
         exit(0);    //结束程序
     }
     idx++;        
     return ;
  }
  //搜索,填充每位上的字符
  for(int i=0;i<len;i++){
      if(!st[i]){    //如果该位的数字没有被用过
         char in=char('a'+i),tmp=path[u];
         path[u]=in;     //将该位置填上数
         st[i]=true;     //标记为该字母以用过
         dfs(u+1,path);   //搜索下一个位置
         st[i]=false;    //回溯
         path[u]=tmp;    //回溯
    }
  }
}
int main()
{  cin>>s;
   len=s.size();    //记录字符串长度
   dfs(0,s);   //搜索每种该长度字符串的组合方式
  return 0;
}

三、知识风暴

DFS

  • 参考这里
  • exit(0):功能—正常运行程序并退出程序,可以用于在非主函数中直接结束程序。

你可能感兴趣的:(蓝桥真题刷刷刷,蓝桥杯,深度优先,算法,图论,数据结构)