P10997 【MX-J3-T4】 Partition 题解
P10997 【MX-J3-T4】 Partition
太长了。看原题吧
好像是一个trick? 非常巧妙!感觉要是紫。
发现红黄绿橙的分界线呈两条对角线的样子。其中黄绿最高点不增,橙绿最高点不降。
再看这个分数怎么统计,先都认为为 1 1 1 ,然后橙绿加一,黄绿加二。发现这样相应的分数是正确的!
红:1,橙:1+1=2,黄:1+2=3,绿:1+1+2=4.
又因为黄绿线和橙绿线是互相独立的,分开DP即可。
其中我们设用 ( i , j ) (i,j) (i,j) 代表这个格子左上角的分界点。 f 1 i , j f1_{i,j} f1i,j 表示到第 i i i 列,分界点在 j j j 及以下最高的黄绿得分。 f 2 i , j f2_{i,j} f2i,j 表示到第 i i i 列,分界点在 j j j 及以上最高的橙绿得分。
f 1 i , j = max ( f 1 i − 1 , j , f 1 i , j − 1 + u d i , j − 1 ) f1_{i,j}= \max(f1_{i-1,j},f1_{i,j-1}+ud_{i,j-1}) f1i,j=max(f1i−1,j,f1i,j−1+udi,j−1) 从上一列分界,或是更低的格子分界得到的最优值。 f 2 f2 f2 同理。
启示: 分数拆分?在这里插入代码片
code:
#include<bits/stdc++.h>
using namespace std;
#define ll long long
const ll INF=0x3f3f3f3f3f3f3f3f;
const int N=2005;
int n,m;
ll f1[N][N],f2[N][N];
ll ud[N][N];
ll a[N][N];
ll sum;
int main(){scanf("%d%d",&n,&m);for(int i=1;i<=n;i++){for(int j=1;j<=m;j++) {scanf("%lld",&a[i][j]);sum+=a[i][j];}}for(int i=0;i<=n+1;i++){for(int j=0;j<=m+1;j++) {f1[i][j]=f2[i][j]=-INF;}}for(int i=n;i>=1;i--){for(int j=1;j<=m;j++){ud[i][j]=ud[i+1][j]+a[i][j];}}f1[0][1]=f2[0][m+1]=0;for(int i=1;i<=n+1;i++){for(int j=1;j<=m+1;j++){//黄绿 f1[i][j]=max(f1[i-1][j],f1[i][j-1]+ud[i][j-1]);}for(int j=m+1;j>=1;j--){f2[i][j]=max(f2[i-1][j],f2[i][j+1]+ud[i][j]);//因为记的是左上角。 }}printf("%lld\n",sum+f1[n+1][m+1]*2+f2[n+1][1]);return 0;
}
