原题链接
题目大意
给你一个
n
∗
m
n*m
n∗m的矩阵,里面有数,如果数字为
0
0
0,就不能走,否则这个数就是经过这个格子所需的代价。请求出从
(
1
,
1
)
(1,1)
(1,1)走到
(
n
,
m
)
(n,m)
(n,m)且只能向右走或向下走的最小代价和路径。
S
a
m
p
l
e
\mathbf{Sample}
Sample
I
n
p
u
t
\mathbf{Input}
Input
4 4
4 10 7 0
3 2 2 9
0 7 0 4
11 6 12 1
S a m p l e \mathbf{Sample} Sample O u t p u t \mathbf{Output} Output
(1,1)->(2,1)->(2,2)->(2,3)->(2,4)->(3,4)->(4,4)
24
H
i
n
t
&
E
x
p
l
a
i
n
\mathbf{Hint\&Explain}
Hint&Explain
解题思路
从
n
,
m
n,m
n,m开始逆循环,即行数从
n
∼
1
n\sim 1
n∼1,列数从
m
∼
1
m\sim 1
m∼1循环,每一次求出从
(
n
,
m
)
(n,m)
(n,m)走到当前位置的最小价值路径的上一步是哪里以及从
(
n
,
m
)
(n,m)
(n,m)走到当前位置的最小价值,分别计为
r
o
a
d
road
road和
d
p
dp
dp,注意,
r
o
a
d
n
,
m
=
(
0
,
0
)
road_{n,m}=(0,0)
roadn,m=(0,0)。
最后从
(
1
,
1
)
(1,1)
(1,1)走到
(
n
,
m
)
(n,m)
(n,m)的最小价值就是
d
p
1
,
1
dp_{1,1}
dp1,1,最小价值路径可以通过
r
o
a
d
road
road递归输出,最重要的一点就是
他
的
最
小
价
值
是
不
算
终
点
的
价
值
的
!
{\color{red}他的最小价值是不算终点的价值的!}
他的最小价值是不算终点的价值的!,例如样例,原本是4+3+2+2+9+4+1=25
,但是终点不算,答案是25-1=24
。
上代码
#include<iostream>
#include<cstring>
#define mp make_pair
using namespace std;
int n,m;
int a[102][102];
int dp[102][102];
pair<int,int> road[102][102];
int main()
{
cin>>n>>m;
for(int i=1; i<=n; i++)
for(int j=1; j<=m; j++)
cin>>a[i][j];
memset(dp,0x3f3f3f3f,sizeof(dp));
dp[n][m]=0;
road[n][m]=mp(0,0);
a[n][m]=0;
for(int i=n; i>=1; i--)
{
for(int j=m; j>=1; j--)
{
if(!a[i][j]) continue;
if(dp[i+1][j]<dp[i][j+1])
{
dp[i][j]=dp[i+1][j]+a[i][j];
road[i][j]=mp(i+1,j);
}
else
{
dp[i][j]=dp[i][j+1]+a[i][j];
road[i][j]=mp(i,j+1);
}
}
}
if(dp[1][1]>=0x3f3f3f3f)
{
cout<<0<<endl;
exit(0);
}
int x=1,y=1;
while(x&&y)
{
cout<<"("<<x<<","<<y<<")";
if(x!=n||y!=m) cout<<"->";
pair<int,int> now=road[x][y];
x=now.first,y=now.second;
// cout<<x<<" "<<y<<endl;
}
cout<<endl;
cout<<dp[1][1];
cout<<endl;
// cout<<road[3][4].first<<" "<<road[3][4].second<<endl;
return 0;
}
完美切题 ∼ \sim ∼