现在的位置: 首页 > 综合 > 正文

跳棋与Fibonacci数列(守恒思想)

2017年12月23日 ⁄ 综合 ⁄ 共 893字 ⁄ 字号 评论关闭

现在有一排挨着放的格子,这一排是无限长,某些格子里面放了一些棋子,现在可以有两个操作:

1.拿出一个格子里的一颗棋子,在其左边的两个格子里分别放入一个棋子;

2.如果两个连续的格子都有棋子,可以从这两个格子分别拿出一个棋子,然后在两个格子的右边这个格子放入一颗棋子;

可见这两个操作是互逆的。

 

现在的任务是:给定一个初始的格子状态,有些格子有棋子,有些格子空着,希望通过上述两种操作,将这个格子带转换为:

1.每个格子最多只有一颗棋子;

2.不能有连续的格子都有棋子;

当然给定的初始序列可以有很多种终止状态,求出任意一种即可。

 

一个直观暴力的方法是将所有大于1个格子变成1,即将多余的棋子全通过操作1放到左边去,相当于向左压平,然后通过操作2向延伸;

这个操作一定是会终止的,因为给定初始格子状态后,操作1一定是有限的,而操作2每次会将棋子数量减少1,所以最终一定会停止;

 

我想介绍的是另一个非常Geek的方法,也是守恒思想的应用。

首先我们看操作1和2,假设4号格子(因为是无限长,所以几号几号都是人为给定一个开始基准设定的)和5号格子各有一颗棋子,那么通过操作2,可以得到6号格子的一颗棋子;

即 4 A+ 5 A = 6 A , A是随意的一个标记,可以理解为有棋子这个情况。

所以,如果我们能给每个格子赋以一个权值,最后是不是能得到点什么呢?

假设第i个格子的权值为 Fi ,那么必有  Fi = F i-1 + F i-2 , 看到这个递推式是不是很眼熟呢,那就是神奇的Fibonacci数列,是不是感到数学很神奇呢?

所以当我们给带子上的所有格子根据Fibonacci数列赋好权值之后,当前给定状态的所有棋子的权值累加和就可以算出来了:

Sum =  Fi * Ai  累加。对吧,而可知我们的操作是守恒的,因此最后的状态的Sum一定也是相等的~

因此既然我们知道这个Sum了,我们就可以直接来构造一个符合这个Sum的最后状态了,根本不在乎中间是怎么转换的。

也就是我们 有一个Sum,要将他分解到Fibonacci数列中某些不相邻项的和~

这个使用贪心就好了,每次取离剩余Sum最近的那个Fibonacci数,然后标记对应的格子放1,直到Sum=0;

 

抱歉!评论已关闭.