bfs广度优先搜索的标记策略与康托展开

在之前的问题中,将已到达的状态使用布尔数组或整数数组进行标记,从而避免重复访问以及得到最小步数等。当一道题的数据范围过大,例如vis数组已经需要开到甚至10^9时,为解决这样的情况带来的问题。一个很显然的方案,可以通过set或map数据结构来标记当前已经访问的位置。对于上面的问题,直接创建map<int,int> mp来标记访问的数字和对应的最小步数。另外在一些时候,需要创建结构体放入set或map中,然而直接将自建类型作为该数据结构的类型是会报错的。这是由于set和map都是基于二叉排序
摘要由CSDN通过智能技术生成

在之前的问题中,将已到达的状态使用布尔数组或整数数组进行标记,从而避免重复访问以及得到最小步数等。
当一道题的数据范围过大,例如vis数组已经需要开到甚至10^9时,为解决这样的情况带来的问题。
一个很显然的方案,可以通过set或map数据结构来标记当前已经访问的位置。对于上面的问题,直接创建map<int,int> mp来标记访问的数字和对应的最小步数。
另外在一些时候,需要创建结构体放入set或map中,然而直接将自建类型作为该数据结构的类型是会报错的。这是由于set和map都是基于二叉排序树(红黑树)的数据结构,所以放入的元素需要满足是能够相互比较的,所以在结构体中,需要实现对<比较方法的重载。
以下是一个例子i,在一个拥有x和y的两个属性的结构体的点中,首先比较x值得大小,如果相同就比较y的大小:

struct Point{
   
	int x,y;
	bool operator < (const Point& rhs) const{
   
		if(x!=rhs.x)
			return x<rhs.x;
		return y<rhs.y;
	}
};

对于类似的排列的序列,我们可以通过 康托展开 的技巧,建立一个从排列到自然数的 双射。康托展开计算该排列在全排列中的顺序来确定自然数,例如对123三个数字所组成的全排列进行排序,从小到大依次为123 132 213 231 312 321,因此123这个排列可以对应到1(同时也可以从1对应到123)。
将一个排列展开为自然数的过程为康托展开,那么如何计算比当前排列字典序小的数量呢,我们可以从高到低位考虑当前的位子,可能有多少数字小于当前位,并称上长度的阶乘。
假设当前全排列为3 4 2 1,具体的计算过程如下,初始化为 i d = 1 id=1 id=1:

  1. 最高位(第三位,从第0位开始从右往左数)为3,那么在全排列中1和2做第三位的都比3开头的小,总共有2×3!个,那么 i d = i d + 2 × 3 ! = 13 id=id+2×3!=13 id=id+2×3!=13
  2. 第二位为4,注意此前提的最高位是3(最高位是1和2的都枚举过了),那么比4小的情况是不能考虑3的,则有1和2, i d = i d + 2 × 2 ! = 17 id=id+2×2!=17 id=id+2×2!=17
  3. 第一位为2,则考虑在3放在第三位,4放在第二位的基础上,此时仅有1会比,所以 i d = i d + 1 × 1 ! = 18 id=id+1×1!=18 id=</
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值