AT_abc227_f
前言
宝藏 Dp 题,值得一做。
思路
我们首先想到的可能就是暴力去 DFS 但是时间复杂度显然过不去,所以我们有能想到从搜索优化到 Dp 但是我们显然不能存下来走的路径。所以我们转变思路,发下 \(n\leq 30\) 那么我们是不是就能想到一个 \(n^5\) 的 Dp 了。其实我们可以枚举出第 \(k\) 大数,这里设定为 \(a_{x,y}\) 然后我们可以分类讨论一下,这里我们定义 \(dp_{i,j,k}\) 为从 \(1,1\) 走到 \(i,j\) 经过了 \(k\) 个能入选最终最大值的数的最小路径。
- 如果 \(a_{i,j}\geq a_{x,y}\) 那么我们由于只能从 \(dp_{i-1,j}\) 和 \(dp_{i,j-1}\) 转移过来所以我们就让 \(dp_{i,j,k}=\min(dp_{i-1,j,k-1}+a_{i,j},dp_{i,j-1,k-1}+a_{i,j},dp_{i,j,k})\),因为这个数能入选。
- 若 \(a_{i,j}\leq a_{x,y}\) 那么我们就让 \(dp_{i,j,k}=\min(dp_{i-1,j,k},dp_{i,j-1,k},dp_{i,j,k})\),毕竟这个数选不上了。
注意:这里的等于可入选两种因为不会影响答案。
最后,答案就是对于每一个 \(a_{x,y}\) 的 \(dp_{n,m,k}\) 的最小值了。
代码
#include <bits/stdc++.h>
using namespace std ;
#define int long long
#define rep(i,x,y) for(int i=x;i<=y;i++)
#define rep1(i,x,y) for(int i=x;i>=y;i--)
#define il inline
int a[50][50];
int n,m,k,ans=0x3f3f3f3f3f3f3f3fll;
int dp[33][33][63];
signed main() {
scanf("%lld%lld%lld",&n,&m,&k);
rep(i,1,n) rep(j,1,m) scanf("%lld",&a[i][j]);
rep(x,1,n) {
rep(y,1,m) {
memset(dp,0x3f,sizeof dp);
dp[0][0][0]=dp[1][0][0]=dp[0][1][0]=false;
rep(i,1,n) {
rep(j,1,m) {
if(a[i][j]>=a[x][y]) rep(t,1,k) dp[i][j][t]=min({dp[i][j][t],dp[i-1][j][t-1]+a[i][j],dp[i][j-1][t-1]+a[i][j]});
if(a[i][j]<=a[x][y]) rep(t,0,k) dp[i][j][t]=min({dp[i][j][t],dp[i-1][j][t],dp[i][j-1][t]});
}
}
ans=min(ans,dp[n][m][k]);
}
}
cout<<ans<<endl;
return false;
}
/*
2 2 1
3 2
4 3
3 5 3
4 7 8 6 4
6 7 3 10 2
3 8 1 10 4
*/

浙公网安备 33010602011771号