找规律解决林克的命运之阵

问题描述

题目

有一个方格型的命运矩阵,矩阵边界在无穷远处。我们做如下假设:

1. 每一个格子象征林克命运中的一次抉择,每次只能从相邻的方格中做选择。

2. 从某个格子出发,只能从当前方格移动一格,走到某个相邻的方格上;

3.选择一旦做出就不可更改,因此走过的格子无法走第二次。

4. 从命运矩阵的第1行出发,只能向下、左、右三个方向走;

请问:如果最高允许在方格矩阵上走n步(也就是林克一生最多能做n个选择)。
那么随着n的不同,请问一共会有多少种不同选择的方案导致多少个不同的林克?
注意,2种走法只要有一步不一样,即被认为是不同的方案。

输入

允许在方格上行走的步数n(n <= 20)

样例

20

输出

经过n个选择之后,诞生的不同的林克的个数。

样例

54608393

思路

我们注意到,向下走的选择正好像树状展开,每走一步树就延展一层,当全部延展完后,最末端的分支的数量就是不同方案的数量。

又因为不能走走过的路,所以我们发现上一步向下走的,这一步可以向下、左、右三个方向走,但如果上一步向左走,这一步就不能向右走,同理,上一步向右走,这一步就不能向左走。我们发现不同的分支可以延展出的分支的数量是不同的。

所以我们用cnt来标记目前分支末端的数量,用mark来标记只能延展两个分支的分支,每次走一步时,分支末端数量就变为(cnt-mark)*3+mark*2,其中,没被mark的分支可以延展两个被mark的分支,被mark的分支可以延展一个被mark的分支。我们用tmp记录走这一步之前的cnt的值,则走完这一步后mark的分支的数量就会变为mark+(tmp-mark)*2。

这种方法是通过找规律得来的,因为题目只要求最后可能的数量,不要求每次走的方向。该方法代码量较少,但不易理解,利用广搜会比较好理解,但代码量会上升。

代码实现和分析

#include<iostream>
using namespace std;
int main() {
    int n, cnt = 1;//走零步,只有一种可能
    cin >> n;
    int mark = 0;//一开始的那步可以向三个方向走,没有被mark
    for (int i = 0; i < n; i++) {//走n步
        int tmp = cnt;//存储走这一步之前分支末端的数量
        cnt = cnt * 3 -mark;//相当于(cnt-mark)*3+mark*2,
//被mark的分支生长出两个分支,没有被mark的分支会生长出三个分支
        mark = mark + (tmp - mark) * 2;//被mark的分支会生长出一个被mark的分支,
//而没有被mark的分支会生长出两个没有被mark的分支
    }
    cout << cnt;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值