传送门:http://www.lydsy.com:808/JudgeOnline/problem.php?id=1187

巨裸的插头dp,没什么好说的。

代码巨丑TAT...

 

#include <iostream>
#include <cstdio>
#include <cstring>
using namespace std;
#define INF 0x3f3f3f3f
const int maxn = 1100;
const int maxm = 80;
const int Hash = 1007;
const int maxk = 10010;
struct node {
    int fir[Hash], edge[maxk], next[maxk], f[maxk], ss[maxk];
    int cnt;
    void cr() {
        memset(fir, -1, sizeof(fir));
        cnt = 0;
    }
    void push(int s, int v) {
        for(int i = fir[s % Hash]; ~i ; i = next[i]) {
            int p = edge[i];
            if(p == s) {
                f[i] = max(f[i], v);
                return;
            }
        }
        edge[cnt] = s;
        next[cnt] = fir[s % Hash];
        fir[s % Hash] = cnt;
        f[cnt] = v;
        ss[cnt ++] = s;
        return;
    }
}d[2];
int n, m, ans = -INF;
int a[maxn][maxm];
int find_pos(int s, int p) {
    return (s >> (p << 1)) & 3;
}
void tp(int &s, int p, int v) {
    s &= (~(3 << (p << 1)));
    s |= (v << (p << 1));
    return;
}
int find_r(int s, int p) {
    int cnt = 0;
    for(int i = p; i <= m; i ++) {
        if(find_pos(s, i) == 1) cnt ++;
        else if(find_pos(s, i) == 2) cnt --;
        if(!cnt) return i;
    }
}
int find_l(int s, int p) {
    int cnt = 0;
    for(int i = p; i >= 0; i --) {
        if(find_pos(s, i) == 2) cnt ++;
        else if(find_pos(s, i) == 1) cnt --;
        if(!cnt) return i;
    }
}
int main() {
    scanf("%d%d", &n, &m);
    for(int i = 1; i <= n; i ++) {
        for(int j = 1; j <= m; j ++) {
            scanf("%d", &a[i][j]);
        }
    }
    int cur = 0;
    d[cur].cr();
    d[cur].push(0, 0);
    for(int i = 1; i <= n; i ++) {
        for(int j = 1; j <= m; j ++) {
            d[cur ^ 1].cr();
            for(int k = 0; k < d[cur].cnt; k ++) {
                int t = d[cur].ss[k], tpos, tf = d[cur].f[k];
                int l = find_pos(t, j - 1), r = find_pos(t, j);
                if(l && r) {
                    if(l == 1 && r == 1) {
                        tpos = find_r(t, j);
                        tp(t, j - 1, 0); tp(t, j, 0); tp(t, tpos, 1);
                        d[cur ^ 1].push(t, tf + a[i][j]);
                    } else if(l == 2 && r == 1) {
                        tp(t, j - 1, 0); tp(t, j, 0);
                        d[cur ^ 1].push(t, tf + a[i][j]);
                    } else if(l == 2 && r == 2) {
                        tpos = find_l(t, j - 1);
                        tp(t, j - 1, 0); tp(t, j, 0); tp(t, tpos, 2);
                        d[cur ^ 1].push(t, tf + a[i][j]);
                    } else {
                        tp(t, j - 1, 0); tp(t, j, 0);
                        if(!t) ans = max(ans, tf + a[i][j]);
                    }
                } else if(l) {
                    if(i < n) {
                        d[cur ^ 1].push(t, tf + a[i][j]);
                    }
                    if(j < m) {
                        tp(t, j - 1, 0); tp(t, j, l);
                        d[cur ^ 1].push(t, tf + a[i][j]);
                    }
                } else if(r) {
                    if(j < m) {
                        d[cur ^ 1].push(t, tf + a[i][j]);
                    }
                    if(i < n) {
                        tp(t, j - 1, r); tp(t, j, 0);
                        d[cur ^ 1].push(t, tf + a[i][j]);
                    }
                } else {
                    d[cur ^ 1].push(t, tf);
                    if(i < n && j < m) {
                        tp(t, j - 1, 1); tp(t, j, 2);
                        d[cur ^ 1].push(t, tf + a[i][j]);
                    }
                }
            }
            cur ^= 1;
        }
        for(int k = 0; k < d[cur].cnt; k ++) {
            d[cur].ss[k] <<= 2;
        }
    }
    printf("%d\n", ans);
    return 0;
}