题解

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

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. Java基础-IO流对象之字节缓冲流(BufferedOutputStream与BufferedInputStream)

    Java基础-IO流对象之字节缓冲流(BufferedOutputStream与BufferedInputStream) 作者:尹正杰 版权声明:原创作品,谢绝转载!否则将追究法律责任. 在我们学习字 ...

  2. 华为手机不能连接android studio进行调试的解决办法

    出现情景:在开启了usb debugging(usb调试模式)后,AS(android studio)还是找不到真机. 解决办法:下载驱动精灵,检测是否安装了huawei的usb驱动,如果没有,安装成 ...

  3. Lena与数字图像处理

    在数字图像处理中,Lena(Lenna)是一张被广泛使用的标准图片,特别在图像压缩的算法研究中. 黑白Lena图   标准Lena (为什么用这幅图,是因为这图的各个频段的能量都很丰富:即有低频(光滑 ...

  4. C语言第九节进制

    进制 什么是进制 是一种计数的方式,数值的表示形式 数一下方块的个数 汉字:十一 十进制:11 二进制:1011 八进制:13 多种进制:十进制.二进制.八进制.十六进制.也就是说,同一个整数,我们至 ...

  5. div内容超出后自动显示滚动条

    一. <div style=" overflow:scroll; width:400px; height:400px;”></div> 记住宽和高一定要设置噢,否则不 ...

  6. 11 Facts about Data Science that you must know

    11 Facts about Data Science that you must know Statistics, Machine Learning, Data Science, or Analyt ...

  7. Could not open input file: artisan

    执行php artisan 命令,报错Could not open input file: artisan artisan 是 Laravel 项目下的指令文件,在Laravel 项目的根目录下可以看 ...

  8. 15、BigDecimal类简介

    BigDecimal类概述 由于在运算的时候,float类型和double很容易丢失精度,在金融.银行等对数值精度要求非常高的领域里面,就不能使用float或double了,为了能精确的表示.计算浮点 ...

  9. 安装Visual Studio Scrum 1.0过程模板

    近几年里,Scrum变成了相当流行的软件开发方法学.因为它轻量.可迭代且快速等优点,以致于在敏捷开发中极受欢迎.微软甚至将TFS2010自带的MSF Agile5.0过程模板做得像Scrum,开发者们 ...

  10. 如何提高单片机Flash的擦写次数

    所谓提高flash的擦写次数,并不是真正的提高flash擦写次数,而是通过以"空间换时间"概念,在软件上实现“操作的次数大于其寿命”.详见链接: http://bbs.eeworl ...