【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('\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」探险路线的更多相关文章
- [LOJ 2070] 「SDOI2016」平凡的骰子
[LOJ 2070] 「SDOI2016」平凡的骰子 [题目链接] 链接 [题解] 原题求的是球面面积 可以理解为首先求多面体重心,然后算球面多边形的面积 求重心需要将多面体进行四面体剖分,从而计算出 ...
- LOJ 3156: 「NOI2019」回家路线
题目传送门:LOJ #3156. 题意简述: 有一张 \(n\) 个点 \(m\) 条边的有向图,边有两个权值 \(p_i\) 和 \(q_i\)(\(p_i<q_i\))表示若 \(p_i\) ...
- LOJ#2070. 「SDOI2016」平凡的骰子(计算几何)
题面 传送门 做一道题学一堆东西不管什么时候都是美好的体验呢-- 前置芝士 混合积 对于三个三维向量\(a,b,c\),定义它们的混合积为\((a\times b)\cdot c\),其中$\time ...
- Loj #2192. 「SHOI2014」概率充电器
Loj #2192. 「SHOI2014」概率充电器 题目描述 著名的电子产品品牌 SHOI 刚刚发布了引领世界潮流的下一代电子产品--概率充电器: 「采用全新纳米级加工技术,实现元件与导线能否通电完 ...
- Loj #3096. 「SNOI2019」数论
Loj #3096. 「SNOI2019」数论 题目描述 给出正整数 \(P, Q, T\),大小为 \(n\) 的整数集 \(A\) 和大小为 \(m\) 的整数集 \(B\),请你求出: \[ \ ...
- Loj #3093. 「BJOI2019」光线
Loj #3093. 「BJOI2019」光线 题目描述 当一束光打到一层玻璃上时,有一定比例的光会穿过这层玻璃,一定比例的光会被反射回去,剩下的光被玻璃吸收. 设对于任意 \(x\),有 \(x\t ...
- Loj #3089. 「BJOI2019」奥术神杖
Loj #3089. 「BJOI2019」奥术神杖 题目描述 Bezorath 大陆抵抗地灾军团入侵的战争进入了僵持的阶段,世世代代生活在 Bezorath 这片大陆的精灵们开始寻找远古时代诸神遗留的 ...
- Loj #2542. 「PKUWC2018」随机游走
Loj #2542. 「PKUWC2018」随机游走 题目描述 给定一棵 \(n\) 个结点的树,你从点 \(x\) 出发,每次等概率随机选择一条与所在点相邻的边走过去. 有 \(Q\) 次询问,每次 ...
- Loj #3059. 「HNOI2019」序列
Loj #3059. 「HNOI2019」序列 给定一个长度为 \(n\) 的序列 \(A_1, \ldots , A_n\),以及 \(m\) 个操作,每个操作将一个 \(A_i\) 修改为 \(k ...
随机推荐
- 视音频数据处理入门:FLV封装格式解析
===================================================== 视音频数据处理入门系列文章: 视音频数据处理入门:RGB.YUV像素数据处理 视音频数据处理 ...
- git使用初探
1.创建文件夹,初始化git 比如在 E:\Study\xuexixuexi\guns 下创建一个guns的文件夹 使用cmd进入该文件夹:输入git init git init 2.添加远程仓库: ...
- Java并发编程原理与实战四十:JDK8新增LongAdder详解
传统的原子锁AtomicLong/AtomicInt虽然也可以处理大量并发情况下的计数器,但是由于使用了自旋等待,当存在大量竞争时,会存在大量自旋等待,而导致CPU浪费,而有效计算很少,降低了计算效率 ...
- SpringCloud(六) Hystrix入门
前提 一个可用的Eureka注册中心(文中以之前博客中双节点注册中心,不重要) 一个连接到这个注册中心的服务提供者 快速入门 项目搭建 搭建一个新maven项目,artifactid为Ribbon-c ...
- soj1763.传球游戏
题目不算很难,dp的转移方程也很容易列出: 设dp[i][j] 代表第i次传球之后球回到j手中的传球数.易得: dp[i][j] = dp[i-1][j-1] + dp[i-1][j-1] 再处理一下 ...
- [php]php时间格式化
1.将毫秒转化为时间格式 date("Y-m-d H:i:s",$millsec);
- windows下用python转换markdown到html
方法一: 安装markdown, pip install markdown, 安装好后,python -m markdown xxx.md -f xxx.html 方法二:安装markdown2, p ...
- c++刷题(21/100)树的打印、矩阵覆盖和括号生成
题目一:把二叉树打印成多行 从上到下按层打印二叉树,同一层结点从左至右输出.每一层输出一行. 思路:一开始以为2维的vector可以直接访问,但是试了是不行,会报错,vector在有值之前不能直接访问 ...
- 防范xss的正确姿势
防范xss的正确姿势 xss攻击是web攻击中非常常见的一种攻击手段.如果你还没有听说过xss攻击,可以先了解xss的相关知识和原理,例如: XSS)" target="_blan ...
- 【FCS NOI2018】福建省冬摸鱼笔记 day5
第五天,也是讲课的最后一天. 数据结构专题,讲师:杨志灿 他的blog我似乎找不到了……以前肯定是在百度博客里面.但是现在百度博客消失了. PPT做的很有感觉,说了很多实用的技巧. 我觉得其实是收获最 ...