这个题一个耿直的思路肯定是先模拟。。

但是我们马上发现这是具有后效性的。。也就是一个从(1,1)开始走,一个从(n,m)开始走的话

这样在相同的时间点我们就没法判断两个路径是否是相交的

于是在dp写挂了之后。。我们妥妥写了一发爆搜。。vis的那种

一旦你用了vis数组之后。。我们就不能再记忆化搜索了。。因为你缺少记录vis数组的状态。。

去了记忆化。。来了发纯爆搜。。果然T了。。但是在codevs上还得了30分。。不错不错。。

不错个锤子,ACM就是TLE

贴TLE代码

#include <iostream>
#include <cstdio>
#include <algorithm>
#include <cstring> using namespace std;
int n,m;
int a[55][55];
int dp[55][55][55][55];
bool vis[55][55];
const int INF=(~0u)>>2;
bool check(int x,int y){
if(x>=1&&x<=n&&y>=1&&y<=m&&!vis[x][y]) return true;
return false;
}
int dfs(int x1,int y1,int x2,int y2,int dep){
// printf("(%d,%d) (%d,%d) DEP:%d\n",x1,y1,x2,y2,dep);
// if(dp[x1][y1][x2][y2]!=-1) if(vis[x1][y1]||vis[x2][y2]) return -INF;else return dp[x1][y1][x2][y2];
if(x1==x2&&y1==y2) return -INF;
if(x1==n&&y1==m&&x2==1&&y2==1) return 0;
int p=-INF;
if(check(x1+1,y1)&&check(x2-1,y2)){vis[x1+1][y1]=vis[x2-1][y2]=true;p=max(p,dfs(x1+1,y1,x2-1,y2,dep+1));vis[x1+1][y1]=vis[x2-1][y2]=false;}
if(check(x1+1,y1)&&check(x2,y2-1)){vis[x1+1][y1]=vis[x2][y2-1]=true;p=max(p,dfs(x1+1,y1,x2,y2-1,dep+1));vis[x1+1][y1]=vis[x2][y2-1]=false;}
if(check(x1,y1+1)&&check(x2-1,y2)){vis[x1][y1+1]=vis[x2-1][y2]=true;p=max(p,dfs(x1,y1+1,x2-1,y2,dep+1));vis[x1][y1+1]=vis[x2-1][y2]=false;}
if(check(x1,y1+1)&&check(x2,y2-1)){vis[x1][y1+1]=vis[x2][y2-1]=true;p=max(p,dfs(x1,y1+1,x2,y2-1,dep+1));vis[x1][y1+1]=vis[x2][y2-1]=false;}
// printf("DP (%d,%d,%d,%d):%d\n",x1,y1,x2,y2,p+a[x1][y1]+a[x2][y2]);
// printf("from (%d,%d,%d,%d),(%d,%d,%d,%d),(%d,%d,%d,%d),(%d,%d,%d,%d)\n",x1+1,y1,x2-1,y2,x1+1,y1,x2,y2-1,x1,y1+1,x2-1,y2,x1,y1+1,x2,y2-1);
return dp[x1][y1][x2][y2]=p+a[x1][y1]+a[x2][y2];
}
int main(){
scanf("%d%d",&n,&m);
int i,j;
for(i=1;i<=n;++i)
for(j=1;j<=m;++j) scanf("%d",&a[i][j]);
memset(dp,-1,sizeof(dp));
printf("%d\n",dfs(1,1,n,m,0));
return 0;
}

我们有一个好办法。。那就是其实我们发现从两边搜到对角。。和从一边搜到对角即(1,1)=>(n,m)+(n,m)=>(1,1)==(1,1)=>(n,m)+(1,1)=>(n,m)

并且我们发现路程相同。。则速度也相同。。因为时间一样就妥妥的了。。

这样搜的话。。手画一下图就能发现。。我们在同一时刻就能判断相交了。。因为时间相同速度相同。。如果终点相同。。等于路程一定,速度不变

则时间是相同的。。

并且我们只需枚举x1,x2,step,因为起点固定在(1,1),则后面的点和起点的关系就是,(x1-1)+(y1-1)=step,即x1+y1=step+2

y1=step+2-x1;同理也有x2,y2

所以这样就能省下一维空间。。(这个感觉有点类似于数据库的范式惹,尽量少的元素决定主键。。主键生成的其他不算数。。

然后我们来贴一发代码

其中判定坐标不是(1,1)应该写成!(x==1&&y==1)或者写成(x!=1||y!=1),千万别丢掉括号!

贴上21ms代码

#include <iostream>
#include <cstdio>
#include <algorithm>
#include <cstring> using namespace std;
int n,m;
int a[55][55];
int dp[55][55][55];
const int INF=(~0u)>>2;
bool check(int x,int y){
if(x>=1&&x<=n&&y>=1&&y<=m) return true;
return false;
}
//相当于把两人放在同一起跑线生成到重点的不相交路线,这样判定相交就容易了很多,两头分别搜容易错开。。用过的后面会访问
//但是从同一点出发,因为速度是相同的,如果相交一定是同时在某一点相交(一定),容易想象不同点交错使用共同点的情况
//考虑到速度相同且起点相同。。仅仅枚举x1,x2就能得出各自的纵坐标,即(x-1)+(y-1)=sum,x+y=sum+2,则y=sum+2-x
int dfs(int x1,int x2,int s){
int y1=s+2-x1,y2=s+2-x2;
// printf("(%d,%d) (%d,%d) DEP:%d\n",x1,y1,x2,y2,dep);
if(dp[x1][x2][s]!=-1) return dp[x1][x2][s];
if(!check(x1,y1)||!check(x2,y2)) {
// printf("PASS BORDER\n");
return dp[x1][x2][s]=-INF;
}
if(s==n+m-2){
// printf("ENOUGH STEP\n");
if(x1==x2&&y1==y2&&x1==n&&y1==m) return dp[x1][x2][s]=0;
return dp[x1][x2][s]=-INF;
}
if(x1==x2&&y1==y2&&(x1!=1||y1!=1)) {//判定特殊点搞错
// printf("JUDGE CROSS POINT\n");
if(x1==n&&y1==m) return dp[x1][x2][s]=0;
return dp[x1][x2][s]=-INF;
}
int p=-INF;
p=max(p,dfs(x1,x2,s+1));
p=max(p,dfs(x1+1,x2,s+1));
p=max(p,dfs(x1,x2+1,s+1));
p=max(p,dfs(x1+1,x2+1,s+1));
// printf("DP (%d,%d,%d,%d):%d\n",x1,y1,x2,y2,p+a[x1][y1]+a[x2][y2]);
// printf("from (%d,%d,%d,%d),(%d,%d,%d,%d),(%d,%d,%d,%d),(%d,%d,%d,%d)\n",x1,s+3-x1,x2,s+3-x2,x1+1,s+3-x1-1,x2,s+3-x2,x1,s+3-x1,x2+1,s+3-x2-1,x1+1,s+3-x1-1,x2+1,s+3-x2-1);
return dp[x1][x2][s]=p+a[x1][y1]+a[x2][y2];
}
int main(){
scanf("%d%d",&n,&m);
int i,j;
for(i=1;i<=n;++i)
for(j=1;j<=m;++j) scanf("%d",&a[i][j]);
memset(dp,-1,sizeof(dp));
printf("%d\n",dfs(1,1,0));
return 0;
}

codevs1169传纸条 不相交路径取最大,四维转三维DP的更多相关文章

  1. CodeVS1169 传纸条 [DP补完计划]

    题目传送门 题目描述 Description 小渊和小轩是好朋友也是同班同学,他们在一起总有谈不完的话题.一次素质拓展活动中,班上同学安排做成一个m行n列的矩阵,而小渊和小轩被安排在矩阵对角线的两端, ...

  2. Codevs1169:传纸条——题解

    题目描述 Description 小渊和小轩是好朋友也是同班同学,他们在一起总有谈不完的话题.一次素质拓展活动中,班上同学安排做成一个m行n列的矩阵,而小渊和小轩被安排在矩阵对角线的两端,因此,他们就 ...

  3. 算法历练之路——传纸条(JAVA)

    传纸条 时间限制: 1Sec 内存限制: 128MB 提交: 36 解决: 16 题目描述小渊和小轩是好朋友也是同班同学,他们在一起 总有谈不完的话题.一次素质拓展活动中,班上同学安排做成一个m行n列 ...

  4. 四维dp,传纸条,方格取数

    四维dp例题 四维dp便是维护4个状态的dp方式 拿题来说吧. 1. 洛谷P1004 方格取数 #include<iostream> #include<cstdio> usin ...

  5. 【暑假集训】HZOI2019 Luogu P1006 传纸条 二三四维解法

    写三次丢失两次,我谔谔,以后再不在博客园先保存我就去死 题目内容 洛谷链接 小渊和小轩是好朋友也是同班同学,他们在一起总有谈不完的话题.一次素质拓展活动中,班上同学被安排坐成一个\(m\)行.\(n\ ...

  6. TYVJ 1011 NOIP 2008&&NOIP 2000 传纸条&&方格取数 Label:多线程dp

    做题记录:2016-08-15 15:47:07 背景 NOIP2008复赛提高组第三题 描述 小渊和小轩是好朋友也是同班同学,他们在一起总有谈不完的话题.一次素质拓展活动中,班上同学安排做成一个m行 ...

  7. P1011 传纸条//dp优化改进状态表示

    P1011 传纸条 时间: 1000ms / 空间: 131072KiB / Java类名: Main 背景 NOIP2008复赛提高组第三题 描述 小渊和小轩是好朋友也是同班同学,他们在一起总有谈不 ...

  8. Wikioi 1169 传纸条

    这道题是我人生第一道双线动规题,因此我觉得还是很有必要记录下来. 刚接触到这道题的时候我第一反应是单线的动规,可是下一秒我就觉得这样做可能会有问题,因为从左上角(以下简称A)到右下角(以下简称B)通过 ...

  9. 蓝桥杯 算法训练 ALGO-36 传纸条

    算法训练 传纸条   时间限制:1.0s   内存限制:512.0MB 问题描述 小渊和小轩是好朋友也是同班同学,他们在一起总有谈不完的话题.一次素质拓展活动中,班上同学安排做成一个m行n列的矩阵,而 ...

随机推荐

  1. 在EXCEL中如何同时冻结行与列?

    鼠标所在的单元格的位置 ,决定了你冻结的行和列.如: 冻结第一行与第一列, 只需要将鼠标置于单元格在第二列,第二行. 点击冻结

  2. 量子化学Gaussian技术实战课 2021年4月9号--12号 远程在线教学

    材料模拟分子动力学课程 3月19号--22号 远程在线课 lammps分子动力学课程 3月12号--15号 远程在线课 第一性原理VASP实战课 3月25号-28号 远程在线课 量子化学Gaussia ...

  3. 白日梦的Elasticsearch实战笔记,ES账号免费借用、32个查询案例、15个聚合案例、7个查询优化技巧。

    目录 一.导读 二.福利:账号借用 三._search api 搜索api 3.1.什么是query string search? 3.2.什么是query dsl? 3.3.干货!32个查询案例! ...

  4. Flink 中极其重要的 Time 与 Window 详细解析(深度好文,建议收藏)

    前言 Flink 是流式的.实时的 计算引擎 上面一句话就有两个概念,一个是流式,一个是实时. 流式:就是数据源源不断的流进来,也就是数据没有边界,但是我们计算的时候必须在一个有边界的范围内进行,所以 ...

  5. Android 开发学习进程0.27 kotlin使用 和viewbinding的使用

    kotlin-android-extensions 插件被废弃 笔者曾经尝试写过一部分的kotlin代码 主要是项目中一些代码是kotlin完成的,其中我认为 kotlin的kotlin-androi ...

  6. 让源码包apache服务被服务管理命令识别

    在默认情况下,源码包服务是不能被系统的服务管理命令所识别和管理的,但是如果我们做一些设定,则也是可以让源码包服务被系统的服务管理命令所识别和管理的.不过笔者并不推荐大家这样做, 因为这会让本来区别很明 ...

  7. Soul API 网关源码解析 02

    如何读开源项目:对着文档跑demo,对着demo看代码,懂一点就开始试,有问题了问社区. 今日目标: 1.运行examples下面的 http服务 2.学习文档,结合divde插件,发起http请求s ...

  8. scrapy-redis非多网址采集的使用

    问题描述 默认RedisSpider在启动时,首先会读取redis中的spidername:start_urls,如果有值则根据url构建request对象. 现在的要求是,根据特定关键词采集. 例如 ...

  9. PHP 框架之一Laravel

    Laravel: Laravel The phpFramework for Web Artisans and one of the best php framework in year 2014. L ...

  10. 僵尸网络(botnet)概念浅析

    僵尸程序 僵尸程序是用于构建僵尸网络以形成大规模攻击平台的恶意代码.僵尸网络是被黑客集中控制的计算机群,其核心特点是黑客能够通过一对多的命令与控制信道操纵感染僵尸程序的主机执行相同的恶意行为,如可同时 ...