算法趣题-Q22

一、问题描述

二、问题分析

        首先需要明确的是每个结点都是不同的所以在分组计算时就无需考虑旋转重复,如图中第一行第二个和第二行第一个被视为不同的结对方式。然后就是对问题的拆分,能够发现对于一个大问题来说,可以将其拆分为若干两个小问题,而这个大问题的解可以由这子问题的解组合出来。即将n个结点分为3组,其中1组为分割组只有两个结点,剩下的结点分为两组,也就是两个子问题组。在实现过程中可以通过使用数组存储避免重复计算,代码如下。

三、代码实现

1.C/C++实现

#include <iostream>
#include <cstring>

using namespace std;

int main()
{
    // counts[i] 存放 i 个人的结对方式
    // 当 i 为奇数时,counts[i] = 0
    int counts[20];
    memset(counts, 0, sizeof(counts));
    counts[0] = counts[2] = 1;

    // 递推
    for (int i = 4; i < 20; i += 2)
        for (int j = 0; j <= i - 2; j += 2)
            counts[i] += counts[j] * counts[i - j - 2];

    cout << counts[16] << endl;
    return 0;
}

2.Python实现

# coding=utf-8

ways = [1, 1]


def get_ways(num):
    if num % 2:
        return 0
    else:
        index = num // 2
        next_index = len(ways)
        # 如果 list 中元素不够则进行扩充
        while next_index <= index:
            tmp = 0
            for i in range(0, next_index):
                tmp += ways[i] * ways[next_index - i - 1]
            ways.append(tmp)
            next_index += 1
        return ways[index]


if __name__ == '__main__':
    print(get_ways(16))

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值