AtCoder - abc150_c

问题描述

我们有两个大小为𝑁的排列𝑃和𝑄(即𝑃,𝑄都是(1, 2, ..., N)的重新排列)。

大小为𝑁的排列有𝑁!种可能。在这些排列中,设𝑃和𝑄分别为字典序第𝑎和第𝑏小的排列。找出∣𝑎−𝑏∣。

注释

对于两个序列𝑋和𝑌,当且仅当存在整数𝑘使得𝑋𝑖=𝑌𝑖 (1≤𝑖<𝑘)时,𝑋被认为是字典序小于𝑌。

约束

  • 2≤𝑁≤8
  • 𝑃和𝑄是大小为𝑁的排列。

输入

输入以以下格式从标准输入给出:

𝑁
𝑃1 𝑃2​ ...... 𝑃𝑁
𝑄1 𝑄2​ ...... 𝑄𝑁

输出

输出∣𝑎−𝑏∣。

示例 1

InputcopyOutputcopy
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

InputcopyOutputcopy
8
7 3 5 4 2 1 6 8
3 8 2 5 4 6 7 1
17517

示例 3

InputcopyOutputcopy
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;
}

  • 9
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值