P3335(蚂蚁寻路 二维dp呜呜呜)

独自空忆成欢 提交于 2019-11-29 06:54:12

题目
在这里插入图片描述一定会保证走出的路线是好几个底在一个水平线高低可能不同的矩形紧挨着。
然后总共有2*k+1个矩阵 第奇数个矩阵比旁边的矩阵高。

剩下的就是二维DP

f[i][j][k][h]:以第i行第j列为右下角而且这是选的第k个矩阵 高度为h 的权值和最大是多少?

1.第i行(定量):第j列与第j-1列是同一个矩形 f[i][j][k][h]=f[i][j-1][k][h]+s[j][i]-s[j][h-1];

2.第i行(定量):
1*.k为奇数:(应该由第k-1个矩形走向k是往高处走的)
f[i][j][k][h]=f[i][j-1][k-1][h*]+s[j][i]-s[j][h-1];(h*<h)
2*.k为偶数:(应该由第k-1个矩形走向k是往低处走的)
f[i][j][k][h]=f[i][j-1][k-1][h*]+s[j][i]-s[j][h-1];(h*>h)

由于第2种情况每次枚举最大的f[i][j-1][k][h*]很慢.所以我们依靠另一个数组g[i][j][k][h][0/1];
g[i][j][k][h][0/1]:以第i行第j列为右下角而且这是选的第k个矩阵 高度小于h/大于h 的f[i][j][k][h]的最大和.

#include<bits/stdc++.h>
using namespace std;
const int N=100+5,INF=0x3f3f3f3f;
int f[N][23][N],g[N][23][N][2],s[N][N],a[N][N];
//f[i][j][k][h]:以第i行第j列为右下角而且这是选的第k个矩阵 高度为h 的权值和最大是多少?
//1.第i行(定量):第j列与第j-1列是同一个矩形 f[i][j][k][h]=f[i][j-1][k][h]+s[j][i]-s[j][h-1];
//2.第i行(定量):{
//    1*.k为奇数:(应该由第k-1个矩形走向k是往高处走的) f[i][j][k][h]=f[i][j-1][k-1][h*]+s[j][i]-s[j][h-1];(h*<h)
//    2*.k为偶数:(应该由第k-1个矩形走向k是往低处走的) f[i][j][k][h]=f[i][j-1][k-1][h*]+s[j][i]-s[j][h-1];(h*>h)
//}
//由于第2种情况每次枚举最大的f[i][j-1][k][h*]很慢.所以我们依靠另一个数组g[i][j][k][h][0/1];
//g[i][j][k][h][0/1]:以第i行第j列为右下角而且这是选的第k个矩阵 高度小于h/大于h 的f[i][j][k][h]的最大和.
int n,m,K;
int DP(){
    K=(K<<1|1);
    for(int k=1;k<=K;++k)//emmm  初始化!
        for(int h=1;h<=n;++h) f[0][k][h]=g[0][k][h][0]=g[0][k][h][1]=-INF;
    int ans=-INF;
    for(int i=1;i<=n;++i){
        for(int j=1;j<=m;++j){
            for(int k=1;k<=K;++k){
                for(int h=1;h<=i;++h) f[j][k][h]=max(f[j-1][k][h],g[j-1][k-1][h][k&1])+s[i][j]-s[h-1][j];
                g[j][k][1][0]=-INF;
                for(int h=2;h<=i;++h) g[j][k][h][0]=max(g[j][k][h-1][0],f[j][k][h-1]);
                g[j][k][i][1]=-INF;
                for(int h=i-1;h>=1;--h) g[j][k][h][1]=max(g[j][k][h+1][1],f[j][k][h+1]);
            }
            ans=max(ans,max(f[j][K][i],g[j][K][i][0]));
        }
    }
    return ans;
}
int main(){
    scanf("%d%d%d",&n,&m,&K);
    for(int i=1;i<=n;++i)
        for(int j=1;j<=m;++j) scanf("%d",&a[i][j]),s[i][j]=s[i-1][j]+a[i][j];
    printf("%d\n",DP());
}
标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!