【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 ...
随机推荐
- 科学计算三维可视化---TraitsUI(控件)
一:文本编辑器 from traits.api import HasTraits,Int,Str,Password from traitsui.api import View,Item,Group,M ...
- axios post 踩坑之 post传参
今天在项目(vue2.0)使用axios进行post请求的时候,使用官方文档的格式传递给后台的数据是一整个json对象,参数已经传递出去了,但是后台获取不到,() 解决方法 利用aixos结合qs来解 ...
- 值得关注的sql-on-hadoop框架
http://www.infoq.com/cn/news/2014/06/sql-on-hadoop 数据的操作语言是SQL,因此很多工具的开发目标自然就是能够在Hadoop上使用SQL.这些工具有些 ...
- windows下自动启动Redis隐藏命令行窗口
这段时间看了看关于Redis的相关内容,对于Redis在windows下的安装和常规启动我就不多说了.可以参考其他的博客http://www.cnblogs.com/edisonchou/p/3821 ...
- idea注册码激活防和谐
1.到网站 http://idea.lanyus.com/ 获取注册码: 2.修改hosts文件,位于C:\Windows\System32\drivers\etc,添加一行,win10推荐使用not ...
- [整理]Node入门 » 一本全面的Node.js教程 - Demo实践所遇到的问题
花了一个上午看完[转载]Node入门 » 一本全面的Node.js教程 根据里面的Demo自己手动实现过程中还是遇到了些问题,特整理在此. <1>.由于node.msi安装包已经自动添加了 ...
- Linux学习2-fork
复制进程映像 fork() 要想让进程同时执行多个函数,我们可以使用线程或从源程序中创建一个完全分离的进程,后者就像init的做法一样,而不像exec调用那样用新程序替换当前指向的线程. 我们可以通过 ...
- 倍增 Tarjan 求LCA
...
- STL-pair
每个pair 可以存储两个值.这两种值无限制. 定义 pair<int,char> p; pair<string,int> p; pair<int,int> p; ...
- translate 与 相对、绝对定位
垂直水平居中是日常前端开发当中一个常见的需求,在支持 CSS3 属性的现代浏览器当中,有一个利用 CSS3 属性的垂直水平居中方法: position absolute; :; :; :transla ...