zoukankan      html  css  js  c++  java
  • 【LOJ】#2068. 「SDOI2016」探险路线

    题解

    少考虑了情况,导致我以为是暴力讨论一次角落移动
    de了两天才反应过来……简直降智

    事实上,我们把移动分三类,一种是在边界跳过一段,一种是在左上角上左上左上左这样撞墙,在右下角下右下右下右这么撞墙,另一种是左右左右左右这么撞墙
    如果你说还有上下上下这么撞墙,就把整个图旋转180度再做一遍dp就好了

    那么就说一种就可以了
    我们在角落里的移动,如果想进行左右洄游的话,就不能再次进行角落移动了,除非我们到了右下角

    那么我们就通过dp求出我们左右洄游之前进行角落移动到了每一行的左右位置时最大价值
    然后进行左右洄游的dp(这个比较简单)
    然后把从上面进行完角落移动和左右洄游的dp的数组和下半部分做完角落移动的拼起来(这个下半部分可以通过把图翻转通过同样的dp求出来)

    这样的话我就只用说一下角落里乱撞的dp怎么写了!
    dp[1/0][i][j]如果是0的话表示这个走到(不一定是撞到)(1,j),之前最远可以达到第i行,1的话是走到(i,1),之前最远可以达到第j列

    转移的时候
    dp[0][i][j] = max(dp[0][i - 1][j],dp[1][i - 1][j - 1] + cost(i,1)->(1,j))
    dp[1][i][j] = max(dp[0][i][j - 1],dp[0][i - 1][j - 1] + cost(1,j)->(i,1))
    同时记录一下0数组减去第一行的前j列前缀和 最大值,用来转移跳跃
    同理还要记录1数组减去第1列前i行前缀和最大值,也是用来转移跳跃的

    这个代码debug得我真是神智不清了
    关键是找来LOJ的AC代码对拍居然这个代码还是错的

    代码

    #include <bits/stdc++.h>
    #define enter putchar('
    ')
    #define space putchar(' ')
    #define pii pair<int,int>
    #define fi first
    #define se second
    #define mp make_pair
    #define MAXN 1000005
    #define mo 999999137
    #define pb push_back
    //#define ivorysi
    using namespace std;
    typedef long long int64;
    typedef double db;
    template<class T>
    void read(T &res) {
        res = 0;T f = 1;char c = getchar();
        while(c < '0' || c > '9') {
            if(c == '-') f = -1;
            c = getchar();
        }
        while(c >= '0' && c <= '9') {
            res = res * 10 + c - '0';
            c = getchar();
        }
        res *= f;
    }
    template<class T>
    void out(T x) {
        if(x < 0) {x = -x;putchar('-');}
        if(x >= 10) out(x / 10);
        putchar('0' + x % 10);
    }
    int N,M;
    int val[805][805],a[805][805];
    int64 col[805][805],row[805][805];
    int64 dp[2][805][805],g[805],R[805],L[805];
    int64 fr[805][2],bh[805][2],ans = -1e16;
    int64 c1[2][805][805],c2[2][805][805];
    int cnt;
    void Init() {
        read(N);read(M);
        for(int i = 1 ; i <= N ; ++i) {
            for(int j = 1 ; j <= M ; ++j) {
                read(val[i][j]);
            }
        }
        for(int i = 1 ; i <= N ; ++i) {
            for(int j = 1 ; j <= M ; ++j) {
                row[i][j] = row[i][j - 1] + a[i][j];
                col[i][j] = col[i - 1][j] + a[i][j];
            }
        }
    
    }
    void update(int64 &x,int64 y) {
        x = max(x,y);
    }
    void Calc(int a[805][805],int n,int m) {
        memset(col,0,sizeof(col));
        memset(row,0,sizeof(row));
        for(int i = 1 ; i <= n ; ++i) {
            for(int j = 1 ; j <= m ; ++j) {
                col[i][j] = col[i - 1][j] + a[i][j];
                row[i][j] = row[i][j - 1] + a[i][j];
            }
        }
        for(int i = 0 ; i <= n ; ++i) {
            for(int j = 0 ; j <= m ; ++j) {
                dp[0][i][j] = dp[1][i][j] = -1e16;
            }
        }
        for(int i = 1 ; i <= n ; ++i) {
            for(int j = 1 ; j <= m ; ++j) {
                dp[0][i][j] = row[1][j];
                dp[1][i][j] = col[i][1];
            }
        }
        for(int j = 1 ; j <= m ; ++j) g[j] = dp[1][1][j] - col[1][1];
        for(int i = 2 ; i <= n ; ++i) {
            int64 t0 = dp[0][i][1] - row[1][1];
            for(int j = 2 ; j <= m ; ++j) {
                dp[0][i][j] = max(dp[0][i - 1][j],dp[1][i - 1][j - 1] + row[i][j] + col[i][j] - a[i][j]);
                update(dp[0][i][j],t0 + row[1][j]);
                update(t0,dp[0][i][j] - row[1][j]);
                dp[1][i][j] = max(dp[1][i][j - 1],dp[0][i - 1][j - 1] + row[i][j] + col[i][j] - a[i][j]);
                update(dp[1][i][j],g[j] + col[i][1]);
                update(g[j],dp[1][i][j] - col[i][1]);
            }
        }
        for(int i = 1 ; i <= n ; ++i) {
            L[i] = -1e16;
            for(int j = 1 ; j <= m ; ++j) {
                update(L[i],dp[1][i][j]);
            }
        }
        R[1] = row[1][m];
        for(int j = 1 ; j <= m ; ++j) g[j] = row[1][m] - row[1][j];
        for(int i = 2 ; i <= n ; ++i) {
            R[i] = -1e16;
            for(int j = 1 ; j < m ; ++j) {
                g[j] = max(g[j] + a[i][m],col[i][j + 1] + row[i][m] - row[i][j + 1]);
                update(R[i],dp[0][i][j] + g[j]);
            }
        }
    }
    void Solve() {
        memcpy(a,val,sizeof(val));
        Calc(a,N,M);
        memset(fr,0,sizeof(fr));memset(bh,0,sizeof(bh));
        for(int i = 1 ; i <= N ; ++i) {
            fr[i][1] = R[i];
            fr[i][0] = L[i];
        }
        for(int i = 1 ; i <= N ; ++i) {
            for(int j = 1 ; j <= M ; ++j) {
                a[i][j] = val[N - i + 1][M - j + 1];
            }
        }
    
        Calc(a,N,M);
        for(int i = 1 ; i <= N ; ++i) {
            bh[i][0] = R[N - i + 1];
            bh[i][1] = L[N - i + 1];
        }
        memset(row,0,sizeof(row));memset(col,0,sizeof(col));
        for(int i = 1 ; i <= N ; ++i) {
            for(int j = 1 ; j <= M ; ++j) {
                row[i][j] = row[i][j - 1] + val[i][j];
                col[i][j] = col[i - 1][j] + val[i][j];
            }
        }
        int64 l = val[1][1],r = row[1][M];
        int64 t0 = l - col[1][1],t1 = r - col[1][M];
        for(int i = 2 ; i <= N ; ++i) {
            l = t0 + col[i][1];r = t1 + col[i][M];
            update(fr[i][0],r + row[i][M] - val[i][M]);
            update(fr[i][1],l + row[i][M] - val[i][1]);
            update(fr[i][0],l);update(fr[i][1],r);
            t0 = max(t0,fr[i][0] - col[i][1]);
            t1 = max(t1,fr[i][1] - col[i][M]);
        }
        t0 = row[N][M],t1 = val[N][M];
        ans = max(ans,t0 + fr[N - 1][0]);
        for(int i = N - 1 ; i >= 2 ; --i) {
            t0 = max(t0 + val[i][1],bh[i][0]);
            t1 = max(t1 + val[i][M],bh[i][1]);
            ans = max(ans,t0 + fr[i - 1][0]);
            ans = max(ans,t1 + fr[i - 1][1]);
        }
    }
    int main() {
    #ifdef ivorysi
        freopen("f1.in","r",stdin);
    #endif
        Init();
        Solve();
        for(int i = 1 ; i <= N ; ++i) {
            for(int j = 1 ; j <= M ; ++j) {
                if(i < j) swap(val[i][j],val[j][i]);
            }
        }
        swap(N,M);
        Solve();
        out(ans);enter;
        return 0;
    }
    
  • 相关阅读:
    ckplayer-超酷网页视频播放器的使用
    我的第一篇博文(Winfrom下WebBrowser控件的使用)
    estore商城案例(四、五)------添加购物车&购物车显示/生成订单&在线支付
    estore商城案例(三)------Filter过滤器:自动登录&权限管理
    estore商城案例(二)------登录&添加商品&商品列表(下)
    estore商城案例(二)------登录&添加商品&商品列表(上)
    myeclipse2014在线安装aptana
    estore商城案例(一)------用户注册&邮件激活(下)
    estore商城案例(一)------用户注册&邮件激活(上)
    使用指南
  • 原文地址:https://www.cnblogs.com/ivorysi/p/9533693.html
Copyright © 2011-2022 走看看