2020CSP-J普及组复赛 D.方格取数(number)(简单dp)
Posted issue是fw
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了2020CSP-J普及组复赛 D.方格取数(number)(简单dp)相关的知识,希望对你有一定的参考价值。
容易想到定义 f [ i ] [ j ] f[i][j] f[i][j]表示前 i i i列处于位置 j j j的花费
定义 W ( i , j , q ) W(i,j,q) W(i,j,q)表示第 i i i列第 m i n ( j , q ) min(j,q) min(j,q)行到第 m a x ( j , q ) max(j,q) max(j,q)行的权值
那么枚举状态 O ( n m ) O(nm) O(nm),转移枚举一个 q q q得到
f [ i ] [ j ] = m a x { f [ i − 1 ] [ q ] + W ( i , j , q ) } \\rm f[i][j]=max\\{f[i-1][q]+W(i,j,q)\\} f[i][j]=max{f[i−1][q]+W(i,j,q)}
复杂度 O ( n 3 ) O(n^3) O(n3)
考虑 f [ i ] [ j ] f[i][j] f[i][j]由 f [ i − 1 ] [ q ] f[i-1][q] f[i−1][q]转移当 q < = j q<=j q<=j时
维护一个 m x mx mx值表示当 q ∈ [ 1 , j − 1 ] q\\in[1,j-1] q∈[1,j−1]时最优的 f [ i − 1 ] [ q ] + W ( i , q , j − 1 ) f[i-1][q]+W(i,q,j-1) f[i−1][q]+W(i,q,j−1)
那么现在走到第 j j j行还需要往下走一格,也就是更新一个 m a x max max即可
m x = m a x ( f [ i − 1 ] [ j ] , m x ) + a [ j ] [ i ] \\rm mx=max(f[i-1][j],mx)+a[j][i] mx=max(f[i−1][j],mx)+a[j][i]
为了考虑 q > j q>j q>j的情况,倒序再做一遍
#include <bits/stdc++.h>
using namespace std;
#define int long long
const int maxn = 1009;
const int inf = 0x3f3f3f3f;
int n,m,a[maxn][maxn],pre[maxn][maxn],f[maxn][maxn];
inline int max(int a,int b){ return a>b?a:b; }
inline void r(int& a)
{
char c = getchar(); bool f = 1;
for(;c<'0' || c>'9';c = getchar()) if (c=='-') f = 0;
for(;c>='0' && c<='9';a = (a+(a<<2)<<1)+(c&15),c = getchar());
if(!f) a = ~(a-1);
}
signed main()
{
r( n ); r( m );
for(int i=1;i<=n;i++)
for(int j=1;j<=m;j++)
{
r( a[i][j] );
pre[i][j] = pre[i-1][j]+a[i][j];
}
for(int j=1;j<=n;j++) f[1][j] = pre[j][1];
/*
f[i][j]由f[i-1][q]转移而来
当q<=j时,随着j的增大,所有f[i-1][0..j]只是增大了一个a[i-1][q]而已
*/
for(int i=2;i<=m;i++)//前m列
{
int mx = -inf;
for(int j=1;j<=n;j++)//当前在位置j
{
mx = max( mx+a[j][i],f[i-1][j]+a[j][i] );
f[i][j] = mx;
}
mx = -inf;
for(int j=n;j>=1;j--)//当前在位置j
{
mx = max( mx+a[j][i],f[i-1][j]+a[j][i] );
f[i][j] = max( f[i][j],mx );
}
}
cout << f[m][n];
return 0;
}
以上是关于2020CSP-J普及组复赛 D.方格取数(number)(简单dp)的主要内容,如果未能解决你的问题,请参考以下文章
等级考试专题五:CSP-J 2020复赛第二题题解(桶排序的应用)