问题描述
我们有两个大小为𝑁的排列𝑃和𝑄(即𝑃,𝑄都是(1, 2, ..., N)的重新排列)。
大小为𝑁的排列有𝑁!种可能。在这些排列中,设𝑃和𝑄分别为字典序第𝑎和第𝑏小的排列。找出∣𝑎−𝑏∣。
注释
对于两个序列𝑋和𝑌,当且仅当存在整数𝑘使得𝑋𝑖=𝑌𝑖 (1≤𝑖<𝑘)时,𝑋被认为是字典序小于𝑌。
约束
- 2≤𝑁≤8
- 𝑃和𝑄是大小为𝑁的排列。
输入
输入以以下格式从标准输入给出:
𝑁 𝑃1 𝑃2 ...... 𝑃𝑁 𝑄1 𝑄2 ...... 𝑄𝑁
输出
输出∣𝑎−𝑏∣。
示例 1
Inputcopy | Outputcopy |
---|---|
3 1 3 2 3 1 2 | 3 |
大小为3的排列有6种: (1, 2, 3)、(1, 3, 2)、(2, 1, 3)、(2, 3, 1)、(3, 1, 2)和(3, 2, 1)。在其中,(1, 3, 2)和(3, 1, 2)在字典序中分别排第2和第5,因此答案是∣2−5∣=3。
示例 2
Inputcopy | Outputcopy |
---|---|
8 7 3 5 4 2 1 6 8 3 8 2 5 4 6 7 1 | 17517 |
示例 3
Inputcopy | Outputcopy |
---|---|
3 1 2 3 1 2 3 | 0 |
思路:我用的是dfs()写的,就是每次dfs(),都要计数一次,还会出现一个排列,就用此时的这个排列去和排列P或排列Q进行比对,比对成功的话就把此时排列成功的计数赋给一个变量,最后再用绝对值相减就可以了
主要是一开始我也没想到可以这样写,就知道它考察的是dfs(深搜)的知识点,之后就没思路了,去网上搜,它们要么用 C++
的 STL
中的 next_permutation()
函数还有树状数组,不太了解,感觉dfs()最熟悉,还简单易懂,就继续用dfs 写了
#include<iostream>
using namespace std;
int a[10],b[10],u,v,z,c[10];
bool str[10];
int n;
void dfs(int x)
{
if(x==n+1)
{
z++;//z就是来计数的
int i;
for(i=1;i<=n;i++)
if(c[i]!=a[i])
break;
if(i>n) u=z;//此时出现的排列和题目中给的排列啊,
//完全相同,把此时的计数值(序号)赋给一个变量,下边的那个一样的操作
for(i=1;i<=n;i++)
if(c[i]!=b[i])
break;
if(i>n) v=z;
}
for(int i=1;i<=n;i++)
{
if(str[i]==false)
{
str[i]=true;
c[x]=i;
dfs(x+1);
str[i]=false;
}
}
}
int main()
{
cin>>n;
for(int i=1;i<=n;i++)
cin>>a[i];
for(int i=1;i<=n;i++)
cin>>b[i];
dfs(1);
//cout<<u<<" "<<v<<"\n";
cout<<abs(u-v);
return 0;
}