吉首大学-WaWa的难题

题目:

HaHa和WaWa是好朋友,他们在临近期末的这段时间一起宅在图书馆学习。
今天HaHa在书上看到一个排列组合题目,思考很久后,仍然找不出其中的规律。
于是他把题目叙述给了WaWa。
题目:
————————————————————————
一个长度为N的排列,由数字1~N组成,它满足两个条件。
1、数字1永远在第一位。
2、任意两个相邻数字之差小于等于2。
现在给出一个N,
你能知道能组成多少个符合条件的排列吗?。
例如:
N=4
1 2 3 4
1 2 4 3
1 3 2 4
1 3 4 2
所以答案为4
————————————————————————
WaWa听后也是一脸懵逼。
现在WaWa想求助于你们,WaWa给出一个正整数N,问你用1~N能组成多少个符合题意的排列。

dfs没做多少,不是很熟悉,这个题目还是很好的例题,其实很容易想到dfs然后打表找规律,但出于我对dfs实在

不是很熟,最后并没有想到怎么打表,看了wf的代码,发现自己对dfs的理解还是不到位,

以下是wf同学的dfs部分核心代码


void dfs(int i,int step)
{
	if(step==n)
	{
		cnt++;
		return ;
	}
	for(int j=i-2;j<=n;j++)
	{
		if(j>=2&&map[j]&&abs(j-i)<=2)
		{
			map[j]=0;
			dfs(j,step+1);//用完以后让他下次继续可以再用
			map[j]=1;//顺序进行,某一步取哪个不影响取另一个,再数学归纳得出 
		}
	}
}

凭借题意是可以想到是深搜,我遇到的问题是,一条路径向下走的同时,如何判断下个节点可以取哪些值,

换而言之,这么多条路径,如何才能在每条路径都标记好每个值的是否被使用?

想了很多,结构体,链表,乱七八糟,看了wf代码,第一感觉就是我对dfs还掌握不到位

wf的代码,核心就是,每次深搜前标记已经使用了该值,然后深搜完这一条路,在另一个节点判断之前,取消该值的被标记的情况,因为搜索是有顺序的,每条线路是相互不影响的,走下一条线路前,要把这条路走到底,必能把标记消除,

微观是这样的,宏观自然也是,换而言之,就是局部成立,整体成立,数学归纳,得出该种方法可以做到全部遍历的功能

然后找规律得出递推式即可

总结,要标记的dfs,可以在dfs前标记,该dfs之后消除,对其他线路不影响,对dfs内线路,有相同根节点,自然而然,标记恒成立,所以对内没有影响。

猜你喜欢

转载自blog.csdn.net/weixin_43916947/article/details/85288497