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];
}
}