⬅ 返回

1.题目

附原题链接https://www.acwing.com/problem/content/1020/

一个商人穿过一个 N×N
 
的正方形的网格,去参加一个非常重要的商务活动。
 
他要从网格的左上角进,右下角出。
 
每穿越中间 1个小方格,都要花费 1个单位时间。
 
商人必须在 (2N−1)个单位时间穿越出去。
 
而在经过中间的每个小方格时,都需要缴纳一定的费用。
 
这个商人期望在规定时间内用最少费用穿越出去。
 
请问至少需要多少费用?
 
注意:不能对角穿越各个小方格(即,只能向上下左右四个方向移动且不能离开网格)。
 
输入格式
第一行是一个整数,表示正方形的宽度 N
后面 N行,每行 N 个不大于 100的正整数,为网格上每个小方格的费用。
 
输出格式
输出一个整数,表示至少需要的费用。
 
数据范围
1≤N≤100
 
输入样例:
5
1  4  6  8  10
2  5  7  15 17
6  8  9  18 20
10 11 12 19 21
20 23 25 29 33
 
输出样例:
109
 
样例解释
样例中,最小值为 109=1+2+5+7+9+12+19+21+33

2.代码

#include <iostream>
#include <algorithm>
#include <cstring>
#include <vector>
#define PI 3.14159
using namespace std;
 
typedef pair<int, int> PII;
typedef long long LL;
const int MAX_INT = 0x3f3f3f3f;
const int N = 1e5 + 15;
const int mod = 1e9 + 7;
int a[105][105];
void solve()
{
    int n;
    cin >> n;
    for (int i = 1; i <= n; i++)
    {
        for (int j = 1; j <= n; j++)
        {
            cin >> a[i][j];
        }
    }
 
    for (int i = 1; i <= n; i++)
    {
        for (int j = 1; j <= n; j++)
        {
            if (i == 1)
            {
                a[i][j] = a[i][j - 1] + a[i][j];
            }
            else if (j == 1)
            {
                a[i][j] = a[i - 1][j] + a[i][j];
            }
            else
            {
                a[i][j] = min(a[i - 1][j], a[i][j - 1]) + a[i][j];
            }
        }
    }
    cout << a[n][n] << endl;
}
 
int main()
{
    ios::sync_with_stdio(false);
    cin.tie(0);
    cout.tie(0);
 
    int T = 1;
    while (T--)
    {
        solve();
    }
}

3.关键点

3.1 2N-1个单位时间 不走回头路

每穿越中间 1 个小方格,都要花费 1个单位时间。商人必须在 (2N−1)个单位时间穿越出去。

由于有N行N列,且必须在(2N-1)的时间出去,相当于不走回头路,只走N行N列。共有N+N-1即2N-1个节点。

3.2 取最小值

3.2.1 对第一行第一列单独处理

for (int i = 1; i <= n; i++)
    {
        for (int j = 1; j <= n; j++)
        {
            if (i == 1)
            {
                a[i][j] = a[i][j - 1] + a[i][j];
            }
            else if (j == 1)
            {
                a[i][j] = a[i - 1][j] + a[i][j];
            }
            else
            {
                a[i][j] = min(a[i - 1][j], a[i][j - 1]) + a[i][j];
            }
        }
    }

3.2.2 初始化把a[0][1]设置为0 其余全为MAX_INT即可

a[0][1] = 0;
    for (int i = 1; i <= n; i++)
    {
        for (int j = 1; j <= n; j++)
        {
            cin >> a[i][j];
        }
    }
    for (int i = 1; i <= n; i++)
    {
        for (int j = 1; j <= n; j++)
        {
            a[i][j] = min(a[i - 1][j], a[i][j - 1]) + a[i][j];
        }
    }