Project Euler Problem 15 (C++和Python代码实现和解析)

本文探讨了一个经典的组合计数问题——格路计数,具体为从2×2网格左上角到右下角有6条路径,求20×20网格的路径数。提供了C++和Python的递归与迭代解决方案。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

Problem 15 : Lattice paths

Starting in the top left corner of a 2×2 grid, and only being able to move to the right and down, there are exactly 6 routes to the bottom right corner.

在这里插入图片描述
How many such routes are there through a 20×20 grid?

1. 格路 (Lattice paths)

格路计数问题是组合计数中比较重要的问题之一。

从2×2网格的左上角开始,只能向右和向下移动,只有6条路到达右下角。

20×20网格有多少这样的路线?

2. 求解分析

这道经典的格路计数题有三种解决方法。点击网页链接,可以看详细的方法介绍。

3. C++ 代码实现

PE0015的类图如下:
在这里插入图片描述

成员变量m_maxNumOfGrids 定义了最大的网格数 20。
成员变量m_matrix[m_maxNumOfGrids+1][m_maxNumOfGrids+1] 定义了二维数组。

成员函数getGridRoutesNew()和iterativeCountRoutes()完成用迭代方法求解。
成员函数getGridRoutes()和recursiveCountRoutes()完成用递归方法求解。

C++ 代码

#include <iostream>
#include <cassert>   // assert()
#include <cstring>   // memset()

using namespace std;

#define RECURSIVE_SOLUTION

class PE0015
{
private:
    static const int m_maxNumOfGrids = 20;
    long long int m_matrix[m_maxNumOfGrids+1][m_maxNumOfGrids+1];

    long long int recursiveCountRoutes (int px, int py);
    long long int iterativeCountRoutes (int px, int py);

public:
    long long int getGridRoutes (int gridSize);
    long long int getGridRoutesNew (int gridSize);
};

long long int PE0015::getGridRoutesNew (int gridSize)
{
    memset(m_matrix, 0, sizeof(m_matrix));

    long long int numOfRoutes = iterativeCountRoutes(gridSize, gridSize);

    return numOfRoutes;
}

long long int PE0015::getGridRoutes (int gridSize)
{
    memset(m_matrix, 0, sizeof(m_matrix));

    long long int numOfRoutes = recursiveCountRoutes (gridSize, gridSize);

    return numOfRoutes;
}
    
long long int PE0015::recursiveCountRoutes (int px, int py)
{
    if (0==px || 0==py)
    {
        return 1;
    }

    if (m_matrix[px][py] != 0)
    {
        return m_matrix[px][py];
    }

    m_matrix[px][py] = recursiveCountRoutes(px, py-1) + recursiveCountRoutes(px-1, py);

    return m_matrix[px][py];
}

long long int PE0015::iterativeCountRoutes (int px, int py)
{
    for(int i=0; i<=px; i++)
    {
        m_matrix[i][0] = 1;
    }

    for(int j=0; j<=py; j++)
    {
        m_matrix[0][j] = 1;
    }

    for(int i=1; i<=px; i++)
    {
        for(int j=1; j<=py; j++)
        {
            m_matrix[i][j] = m_matrix[i-1][j] + m_matrix[i][j-1];
        }
    }

    return m_matrix[px][py];
}

int main()
{
    PE0015 pe0015;

    assert(6 == pe0015.getGridRoutes(2));

#ifdef RECURSIVE_SOLUTION

    cout << "There are routes " << pe0015.getGridRoutes(20);
    cout << " through a 20x20 grid." << endl;

#else  // ITERATIVE_SOLUTION

    cout << "There are routes " << pe0015.getGridRoutesNew(20) ;
    cout << " through a 20x20 grid." << endl;

#endif

    return 0;
}

4. Python 代码实现

Python的实现方法跟C++一样,也分别实现了迭代和递归求解方法。

特别要注意的是:Python列表list用于二位数组matrix[i][j]是有条件的: 就是可以读取值,不能赋值,为了解决这个局限,我们使用了numpy,matrix[i][j]既可以读取值也可以赋值。

通过这句:matrix = np.zeros((px+1, py+1)) ,就完成了二维数组matrix的定义和初始化。

Python 代码

import numpy as np
    
def getGridRoutesNew(gridSize):
    numOfRoutes = iterativeCountRoutes(gridSize, gridSize)
    return numOfRoutes

def iterativeCountRoutes(px, py):
    """ take iterative method """
    matrix = np.zeros((px+1, py+1))
    
    for i in range(0, px+1):
        matrix[i][0] = 1

    for j in range (0, py+1):
        matrix[0][j] = 1

    for i in range(1, px+1):
        for j in range(1, py+1):
            matrix[i][j] = matrix[i-1][j] + matrix[i][j-1];
 
    return int(matrix[px][py])

def getGridRoutes (gridSize):
    numOfRoutes = recursiveCountRoutes (gridSize, gridSize)
    return numOfRoutes

def recursiveCountRoutes(px, py):
    """ take recursive method """
    matrix = np.zeros((px+1, py+1))
    
    if (0==px or 0==py):
        return 1;
    
    if 0 != matrix[px][py]:
        return matrix[px][py]
    
    matrix[px][py] = recursiveCountRoutes(px, py-1) + recursiveCountRoutes(px-1, py);
    
    return int(matrix[px][py])

def main():
    assert 6 == getGridRoutes(2)
    print("There are routes", getGridRoutesNew(20)," through a 20x20 grid.")

if  __name__ == '__main__':
    main()
 
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值