题解

少考虑了情况,导致我以为是暴力讨论一次角落移动

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('\n')
#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;
}

【LOJ】#2068. 「SDOI2016」探险路线的更多相关文章

  1. [LOJ 2070] 「SDOI2016」平凡的骰子

    [LOJ 2070] 「SDOI2016」平凡的骰子 [题目链接] 链接 [题解] 原题求的是球面面积 可以理解为首先求多面体重心,然后算球面多边形的面积 求重心需要将多面体进行四面体剖分,从而计算出 ...

  2. LOJ 3156: 「NOI2019」回家路线

    题目传送门:LOJ #3156. 题意简述: 有一张 \(n\) 个点 \(m\) 条边的有向图,边有两个权值 \(p_i\) 和 \(q_i\)(\(p_i<q_i\))表示若 \(p_i\) ...

  3. LOJ#2070. 「SDOI2016」平凡的骰子(计算几何)

    题面 传送门 做一道题学一堆东西不管什么时候都是美好的体验呢-- 前置芝士 混合积 对于三个三维向量\(a,b,c\),定义它们的混合积为\((a\times b)\cdot c\),其中$\time ...

  4. Loj #2192. 「SHOI2014」概率充电器

    Loj #2192. 「SHOI2014」概率充电器 题目描述 著名的电子产品品牌 SHOI 刚刚发布了引领世界潮流的下一代电子产品--概率充电器: 「采用全新纳米级加工技术,实现元件与导线能否通电完 ...

  5. Loj #3096. 「SNOI2019」数论

    Loj #3096. 「SNOI2019」数论 题目描述 给出正整数 \(P, Q, T\),大小为 \(n\) 的整数集 \(A\) 和大小为 \(m\) 的整数集 \(B\),请你求出: \[ \ ...

  6. Loj #3093. 「BJOI2019」光线

    Loj #3093. 「BJOI2019」光线 题目描述 当一束光打到一层玻璃上时,有一定比例的光会穿过这层玻璃,一定比例的光会被反射回去,剩下的光被玻璃吸收. 设对于任意 \(x\),有 \(x\t ...

  7. Loj #3089. 「BJOI2019」奥术神杖

    Loj #3089. 「BJOI2019」奥术神杖 题目描述 Bezorath 大陆抵抗地灾军团入侵的战争进入了僵持的阶段,世世代代生活在 Bezorath 这片大陆的精灵们开始寻找远古时代诸神遗留的 ...

  8. Loj #2542. 「PKUWC2018」随机游走

    Loj #2542. 「PKUWC2018」随机游走 题目描述 给定一棵 \(n\) 个结点的树,你从点 \(x\) 出发,每次等概率随机选择一条与所在点相邻的边走过去. 有 \(Q\) 次询问,每次 ...

  9. Loj #3059. 「HNOI2019」序列

    Loj #3059. 「HNOI2019」序列 给定一个长度为 \(n\) 的序列 \(A_1, \ldots , A_n\),以及 \(m\) 个操作,每个操作将一个 \(A_i\) 修改为 \(k ...

随机推荐

  1. bzoj千题计划147:bzoj1207: [HNOI2004]打鼹鼠

    http://www.lydsy.com/JudgeOnline/problem.php?id=1207 dp[i] 表示打的最后一只鼹鼠是第i只,最多能打多少只鼹鼠 输出max(dp[i]) 错解: ...

  2. ZeroMQ API(五) 传输模式

    1.使用TCP的单播传输:zmq_tcp(7) 1.1 名称 zmq_tcp - 使用TCP的ZMQ单播传输 1.2 概要 TCP是一种无处不在,可靠的单播传输.当通过具有ZMQ的网络连接分布式应用程 ...

  3. java反射动态加载类Class.forName();

    1,所有的new出来的对象都是静态加载的,在程序编译的时候就会进行加载.而使用反射机制Class.forName是动态加载的,在运行时刻进行加载. 例子:直接上两个例子 public class Ca ...

  4. Tetrahedron(Codeforces Round #113 (Div. 2) + 打表找规律 + dp计数)

    题目链接: https://codeforces.com/contest/166/problem/E 题目: 题意: 给你一个三菱锥,初始时你在D点,然后你每次可以往相邻的顶点移动,问你第n步回到D点 ...

  5. js鼠标自定移入输入框文本框光标自动定位到文本框

    1.干货直接上 选中输入框设置如下: document.getElementById("Text1").focus();

  6. Dream------scala--Tuple、Array、Map与文件操作

    1.Tuple(元组) 一般使用中,假设一个函数返回多个值,我们可以使用tuple接受这个(val (x,y) = myfunction) package com.wls.scala.hello /* ...

  7. JBoss6.1.0修改启动jvm内存以及修改日志级别【转】

    转自 JBoss6.1.0修改启动jvm内存以及修改日志级别 - liangbinny的专栏 - 博客频道 - CSDN.NEThttp://blog.csdn.net/liangbinny/arti ...

  8. HTTP之二 http 301 和 302的区别

    1.什么是301转向?什么是301重定向? 301转向(或叫301重定向,301跳转)是当用户或搜索引擎向网站服务器发出浏览请求时,服务器返回的HTTP数据流中头信息(header)中的状态码的一种, ...

  9. mysql -> 备份与恢复_11

    备份恢复原理 逻辑备份 物理备份 备份工具

  10. 19 Error handling and Go go语言错误处理

    Error handling and Go go语言错误处理 12 July 2011 Introduction If you have written any Go code you have pr ...