【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 ...
随机推荐
- [php]mysql操作流程
这种是比较老的一种mysql连接方法 1.连接数据库 $this->con = mysql_connect($this->host, $this->user, $this->p ...
- 20155224 2016-2017-2 《Java程序设计》第7周学习总结
20155224 2016-2017-2 <Java程序设计>第7周学习总结 教材学习内容总结 第十二章 标准API的函数接口 Consumer接口:接受一个自变量,处理不返回值. Fun ...
- 【译】第二篇 Replication:分发服务器的作用
本篇文章是SQL Server Replication系列的第二篇,详细内容请参考原文. 分发服务器是SQL Server复制的核心组件.分发服务器控制并执行数据从一个服务器移动到另一个服务器的进程. ...
- 【译】第三篇 Integration Services:增量加载-Adding Rows
本篇文章是Integration Services系列的第三篇,详细内容请参考原文. 增量加载是什么增量加载仅加载与先前加载差异的.差异包括:->新增的行->更新的行->删除的行通过 ...
- solr简介——(九)
下载: http://archive.apache.org/dist/lucene/solr/ 1.什么是solr Solr 是Apache下的一个顶级开源项目,采用Java开发,它是基于Lu ...
- libevent简介和使用【转】
转自:http://www.open-open.com/lib/view/open1386510630330.html libevent是一个基于事件触发的网络库,memcached底层也是使用lib ...
- linux下的usb抓包方法【转】
转自:http://blog.chinaunix.net/uid-11848011-id-4508834.html 1.配置内核使能usb monitor: make menuconfig ...
- Flask--wtforms快速使用和表单验证(附示例)
一.Form类 表单提供WTForms中最高级别的API.它们包含您的字段定义,委托验证,获取输入,聚合错误,并且通常用作将所有内容组合在一起的粘合剂. class wtforms.form.Form ...
- linux文件管理 -> 系统目录结构
几乎所有的计算机操作系统都是用目录结构组织文件.具体来说就是在一个目录中存放子目录和文件, 而在子目录中又会进一步存放子目录和文件,以此类推形成一个树状的文件结构,由于其结构很像一棵树的分支, 所以该 ...
- centos7 部署镜像仓库 harbor
=============================================== 2018/4/16_第2次修改 ccb_warlock 更新 ...