矩阵路径求和问题

题目描述

给定一个m行n列的数字矩阵,计算从左到右走过该矩阵且经过的方格中整数最小的路径。一条路径可以从第1列的任意位置出发,到达第n列的任意位置,每一步为从第i列走到第i+1列的相邻行(水平移动或沿45度斜线移动)。第1行和最后一行看作是相邻的,即应当把这个矩阵看成是一个卷起来的圆筒。

两个略有不同的5行6列的数字矩阵的最小路径如图所示,只有最下面一行的数不同。右边矩阵的路径利用了第 1行与最后一行相邻的性质。

输入格式

包含多个矩阵,每个矩阵的第 1行为两个数 m和n,分别表示矩阵的行数和列数,接下来的mXn个整数按行优先的顺序排列,即前n个数组成第1行,接下来的n个数组成第2行,以此类推。相邻整数间用一个或多个空格分隔,注意这些数不一定是正数。在输人中可能有一个或多个矩阵描述,直到输人结束。每个矩阵的行数在1到10之间,列数在1到100之间。

输出格式

对每个矩阵输出两行,第1行为最小整数之和的路径,路径由n个整数组成,表示路径经过的行号,如果这样的路径不止一条,输出字典序最小的一条。

样例

输入

5 6

3 4 1 2 8 6

6 1 8 2 7 4

5 9 3 9 9 5

8 4 1 3 2 6

3 7 2 8 6 4

输出

1 2 3 4 4 5

16

题解

#include<iostream>

#include<vector>

#include<limits>

#include<algorithm>

using namespace std;

const int M = 20;

const int N = 100;// 定义常量M和N,分别表示预定义的数组的最大行数和列数

const int INF = numeric_limits<int>::max();// 定义一个无穷大值,用于表示无穷大路径长度

int mymin(int a, int b, int c, int& idx) // 函数返回三个参数中的最小值引用参数,更新引用的idx值  

{

    int n_min = a;

    idx = -1;

    if (b < n_min)

    {

        n_min = b;

        idx = 0;  

    }

    if (c < n_min)

    {

        n_min = c;

        idx = 1;  

    }

    return n_min;

}

int main()

{

    int m, n;

    cin >> m >> n;

    int arr[M][N], mypath[M][N];

    int last_path;//存储最短路径

    for (int i = 0; i < m; ++i)

    {

        for (int j = 0; j < n; ++j)

        {

            cin >> arr[i][j];

            mypath[i][j] = -1;  // 初始化mypath数组为-1,表示无效的路径索引

        }

    }

    for (int i = 1; i < n; ++i)

    {

        for (int j = 0; j < m; ++j)

        {

            int idx;// 定义一个索引变量用于存储最小路径的索引值

            arr[j][i] += mymin(arr[(j - 1 + m) % m][i - 1], arr[j][i - 1], arr[(j + 1) % m][i - 1], idx);

            mypath[j][i] = (j + idx + m) % m;  

        }

    }

    int min_path = INF;

    for (int i = 0; i < m; ++i)//动态规划计算到达每个格子的最短路径长度

    {

        if (arr[i][n - 1] < min_path)

        {

            min_path = arr[i][n - 1];

            last_path = i;

        }

    }

    vector<int> path;

    int current_path = last_path;

    for (int j = n - 1; j >= 0; --j)

    {

        path.push_back(current_path);// 将当前路径添加到path的尾部  

        current_path = mypath[current_path][j];// 更新当前路径

    }

    reverse(path.begin(), path.end());

    cout << endl;

    for (int i = 0; i < path.size(); ++i)

    {

        cout  << path[i]+1 ;

        if (i < path.size() - 1) cout << " ";

    }

    cout << endl;

    cout << min_path << endl;

    return 0;

}

输出结果

小结

开始我简单的写了一个贪心算法的程序,但是我很快发现我的输出结果与样例输出结果不同。对于算法来说我认为我的程序本身是没有问题的,只是输出结果不是最优解,而实验样例的输出是最优解。众所周知贪心算法并不总是能够得到问题的最优解,而是得到一个接近最优解的结果。为了实现样例输出,我决定重新编写代码,采用DP实现。

  • 23
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值