F. Decreasing Heights(DP&贪心)
Posted 酷酷的Herio
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了F. Decreasing Heights(DP&贪心)相关的知识,希望对你有一定的参考价值。
F. Decreasing Heights(DP&贪心)
传送门
因为目标路径肯定是如上图形式,所以我们可以预处理每个坐标的高度.
从下标
(
0
,
0
)
(0,0)
(0,0)开始让
a
[
i
]
[
j
]
=
a
[
i
]
[
j
]
−
(
i
+
j
)
a[i][j]=a[i][j]-(i+j)
a[i][j]=a[i][j]−(i+j)
(
p
s
:
若
从
(
1
,
1
)
开
始
走
,
则
要
减
去
(
i
+
j
−
2
)
(ps:若从(1,1)开始走,则要减去(i+j-2)
(ps:若从(1,1)开始走,则要减去(i+j−2),因为起点
(
1
,
1
)
(1,1)
(1,1)的
x
+
y
=
2
x+y=2
x+y=2.)
这样就从走高度加1层的点变成了走到同高度的点。
根据贪心的思想,最终高度的值肯定是在后来的
a
[
i
]
[
j
]
a[i][j]
a[i][j]里面取。所以枚举
n
×
m
n\\times m
n×m个点的高度为最终高度,进行从左上角到右下角的
d
p
dp
dp即可。
时间复杂度: O ( n 4 ) O(n^4) O(n4)
AC代码:
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N =1e2+5;
const ll inf= 0x3f3f3f3f3f3f3f3f;
ll a[N][N],b[N][N],dp[N][N];
int t,n,m;
ll fun(int x,int y)//枚举最终地图路径的值为a[x][y]
for(int i=0;i<n;i++)
for(int j=0;j<m;j++)
b[i][j]=a[i][j]-a[x][y],dp[i][j]=inf;//b[i][j]表示到达(i,j)需要进行多少次操作.
if(b[0][0]<0||b[n-1][m-1]<0) return inf;//剪枝.
dp[0][0]=b[0][0];
for(int i=0;i<n;i++)//简单dp
for(int j=0;j<m;j++)
if(b[i][j]<0) continue;//该点走不了就跳过.
if(i&&b[i-1][j]>=0) dp[i][j]=min(dp[i][j],dp[i-1][j]+b[i][j]);
if(j&&b[i][j-1]>=0) dp[i][j]=min(dp[i][j],dp[i][j-1]+b[i][j]);
return dp[n-1][m-1];
int main()
scanf("%d",&t);
while(t--)
scanf("%d%d",&n,&m);
for(int i=0;i<n;i++)
for(int j=0;j<m;j++) scanf("%lld",&a[i][j]),a[i][j]-=(i+j);//避免考虑要走到+1层.
ll ans=inf;
for(int i=0;i<n;i++)
for(int j=0;j<m;j++)
ans=min(ans,fun(i,j));
printf("%lld\\n",ans);
return 0;
以上是关于F. Decreasing Heights(DP&贪心)的主要内容,如果未能解决你的问题,请参考以下文章
Codeforces 1353F Decreasing Heights(dp)
Codeforces 1353F Decreasing Heights(dp)
BNUOJ 52325 Increasing or Decreasing 数位dp