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

本文介绍了解决欧拉项目第81题的方法,该题要求在80x80矩阵中找到从左上角到右下角的最小路径和,仅允许向右和向下移动。通过动态规划算法,文章提供了C++和Python的实现代码,并验证了算法的正确性。

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

Problem 81 : Path sum: two ways

In the 5 by 5 matrix below, the minimal path sum from the top left to the bottom right, by only moving to the right and down, is indicated in bold red and is equal to 2427.

在这里插入图片描述
Find the minimal path sum, in matrix.txt (right click and “Save Link/Target As…”), a 31K text file containing a 80 by 80 matrix, from the top left to the bottom right by only moving right and down.

1. 欧拉项目第81道题 路径之和:两个方向

在下面的5×5矩阵中,仅向右和向下移动,从左上角到右下角的最小路径之和,用粗体红色表示,等于2427。
在这里插入图片描述
在文件matrix.txt(右键单击保存)中,这是一个包含80x80矩阵的31K大小的文本文件,从左上角到右下角,只需向右和向下移动,找到最小路径之和。

2. 求解分析

可以参考 Problem 67 : Maximum path sum II 。第67道题求解两个方向的最大路径之和,第81道题求解两个方向的最小路径之和。第67道题只有矩阵的一半,是三角矩阵,第81道题是完整的矩阵。

3. C++ 代码实现

C++代码实现的时候,增加了两个编译开关,CPP_11和UNIT_TEST_PRINT_MATRIX_ELEMENTS。

主要求解过程在函数 getMinimalPathSumOfMatrix(const int widthOrHeightOfMatrix) 里实现。

为了验证方法是否正确,检验了5x5的矩阵数据和结果。

C++代码

#include <iostream>
#include <fstream>
#include <sstream>
#include <string>     // stoi()
#include <algorithm>  // min()
#include <cassert>    // assert()

using namespace std;

#define CPP_11  // C++ 11

// #define UNIT_TEST_PRINT_MATRIX_ELEMENTS

class PE0081
{
private:
    static const int max_WidthOrHeight = 80;
    int Matrix[max_WidthOrHeight+1][max_WidthOrHeight+1];

    void printMatrixElements(const int widthOrHeightOfMatrix);

    void handle_unit_test_data();
    void readDataFromFile(const char *filename);

public:
    int getMinimalPathSumOfMatrix(const int widthOrHeightOfMatrix);
};

void PE0081::printMatrixElements(const int widthOrHeightOfMatrix)
{
    for (int row = 0; row <= widthOrHeightOfMatrix; row++)
    {
        for (int col = 0; col <= widthOrHeightOfMatrix; col++)
        {
            cout << Matrix[row][col] << " ";
        }
        cout << endl;
    }
    cout << endl;
}

int PE0081::getMinimalPathSumOfMatrix(const int widthOrHeightOfMatrix)
{
    if (5 == widthOrHeightOfMatrix)
    {
        handle_unit_test_data();
    }
    else // widthOrHeightOfMatrix == 80
    {
        readDataFromFile("p081_matrix.txt");
    }
    
#ifdef UNIT_TEST_PRINT_MATRIX_ELEMENTS
    printMatrixElements(widthOrHeightOfMatrix);
#endif

    for (int row = 1; row <= widthOrHeightOfMatrix; row++)
    {
        for (int col = 1; col <= widthOrHeightOfMatrix; col++)
        {
            if (Matrix[row][col-1] == 0 && Matrix[row-1][col] != 0)
            {
                Matrix[row][col] += Matrix[row-1][col];
            }
            else if (Matrix[row][col-1] != 0 && Matrix[row-1][col] == 0)
            {
                Matrix[row][col] += Matrix[row][col-1];
            }
            else if (Matrix[row][col-1] != 0 && Matrix[row-1][col] != 0)
            {
                Matrix[row][col] += min(Matrix[row][col-1], Matrix[row-1][col]);
            }
        }
    }

#ifdef UNIT_TEST_PRINT_MATRIX_ELEMENTS
    printMatrixElements(widthOrHeightOfMatrix);
#endif

    return Matrix[widthOrHeightOfMatrix][widthOrHeightOfMatrix];
}

void PE0081::handle_unit_test_data()
{
    int Matrix5x5[5][5] = 
    {
        {131, 673, 234, 103, 18 },
        {201,  96, 342, 965, 150},
        {630, 803, 746, 422, 111},
        {537, 699, 497, 121, 956},
        {805, 732, 524,  37, 331}
    };

    memset(Matrix, 0, sizeof(Matrix));

    int widthOrHeightOfMatrix = 5;
    for (int i = 1; i <= widthOrHeightOfMatrix; i++)
    {
        for (int j = 1; j <= widthOrHeightOfMatrix; j++)
        {
            Matrix[i][j] = Matrix5x5[i-1][j-1];
        }
    }
}

void PE0081::readDataFromFile(const char *filename)
{
    int widthOrHeightOfMatrix = 80;

    memset(Matrix, 0, sizeof(Matrix));

    ifstream in(filename);

    if (!in)
    {
        cout << filename << " can't be opened successfully." << endl;
        exit(0);
    }
 
    int row = 1, col;
    string digits_str;
    char szBuf[1024];

#ifdef CPP_11
    while (in.getline(szBuf, 512))
    {
        col = 1;
        istringstream istr(szBuf);
        while (!istr.eof())
        {
            getline(istr, digits_str, ',');
            Matrix[row][col++] = stoi(digits_str); // C++11
        }
        row++;
    }
#else
    while (in.getline(szBuf, 512))
    {
        col = 1;
        string strText = szBuf;
        for (unsigned int i = 0; i < strText.size(); i++)
        {
            if (',' == strText[i])
            {
                strText[i] = ' '; // replace ',' with ' '
            }
        }
        istringstream s(strText);
        int number;
        while (col <= widthOrHeightOfMatrix)
        {
            s >> number;
            Matrix[row][col++] = number;
        }
        row++;
    }
#endif
}
    
int main()
{
    PE0081 pe0081;

    assert(2427 == pe0081.getMinimalPathSumOfMatrix(5));

    cout << "The minimal path sum in matrix.txt containing a 80x80 matrix is ";
    cout << pe0081.getMinimalPathSumOfMatrix(80) << "." << endl;

    return 0;
}

4. Python 代码实现

Python和C++采用了一样的方法,找到最小路径之和在函数getMinimalPathSumOfMatrixMatrix(Matrix)实现。Python跟C++不一样的地方在handle_unit_test_data()和readDataFromFile()。

Python代码

def handle_unit_test_data():
    Matrix5x5 = \
        [[131, 673, 234, 103, 18 ],
         [201,  96, 342, 965, 150],
         [630, 803, 746, 422, 111],
         [537, 699, 497, 121, 956],
         [805, 732, 524,  37, 331]]

    matrix = [ [0]*6 for i in range(6) ]

    for i in range(1, 6):
        for j in range(1, 6):
            matrix[i][j] = Matrix5x5[i-1][j-1]
     
    return matrix
        
def readDataFromFile(filename):
    matrix = [ [0]*81 ]
    for line in open(filename).readlines():
        row_list = [ 0 ]
        for s in line.split(','):
            row_list += [ int(s) ]
        matrix += [ row_list ]

    return matrix

def getMinimalPathSumOfMatrix(Matrix):
    widthOrHeightOfMatrix = len(Matrix) - 1
    for row in range(1, widthOrHeightOfMatrix+1):
        for col in range(1, widthOrHeightOfMatrix+1):
            if Matrix[row][col-1] == 0 and Matrix[row-1][col] != 0:
                Matrix[row][col] += Matrix[row-1][col]
            elif Matrix[row][col-1] != 0 and Matrix[row-1][col] == 0:
                Matrix[row][col] += Matrix[row][col-1]
            elif Matrix[row][col-1] != 0 and Matrix[row-1][col] != 0:
                Matrix[row][col] += min(Matrix[row][col-1], Matrix[row-1][col])

    return Matrix[widthOrHeightOfMatrix][widthOrHeightOfMatrix]
    
def main():
    matrix = handle_unit_test_data()
    assert 2427 == getMinimalPathSumOfMatrix(matrix)
    
    matrix = readDataFromFile('p081_matrix.txt')
    print("The minimal path sum in matrix.txt containing a 80x80 matrix is %d." 
          % getMinimalPathSumOfMatrix(matrix))
    
if  __name__ == '__main__':
    main()
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值