这道题是我人生第一道双线动规题,因此我觉得还是很有必要记录下来。

刚接触到这道题的时候我第一反应是单线的动规,可是下一秒我就觉得这样做可能会有问题,因为从左上角(以下简称A)到右下角(以下简称B)通过动规采用了最优线路,从B到A又用动规找出了一条最优线路且不与之前从A到B的线路有交叉,但是这样总权值却未必是最大的。因为DP都中断了,所以无法确保是最大权值,你可以自己列举出例子,这里就不说了。也许有人会想,我不中断不就行了,到达从B到A中途的某个点C时的权值等于未经过C点且能到达C点所有路径中权值最大的那个再加上C点的值。那行,请问代码你要怎么写?想想都觉得麻烦而且无从下手,题做多了你就有种直觉这样不是最直观最简便最具有“答案范”的答案。

接下来我想到的是广搜。找出从A到B点再从B到A点的不重复道路可以看作是从A点出发寻找两条不相交的道路到达B点,至于说从A点到B点时只能往右和往下传纸条,从B点到A点只能往上和往左传纸条无非就是告诉你每个点只可能从两个方向到达。于是,从A点出发寻找两条不相交的道路到达B点,而且又只能往下和往右走,那么一定是在走了M+N-2步后到达B点,M是行数,N是列数。因为对于每一条线路来说,你要么往右走,要么往下走,那么从A到B需要往下走M-1步,往右走N-1步,加起来就是M+N-2步。那我从1迭代到M+N-2步,广搜搜出每一步有可能达到的所有点对组合不就行了么?确实是行的,比起第一个想法要实际得多,但仍然是非常耗时,因为在每一次的迭代当中,我有可能重复搜了同一个点对,这就导致了我在下一次迭代当中又有可能重复搜了另外一个点对,而且这种重复是呈指数增长的。为什么会重复?当有两个点对A和B都有可能达到同一个点对C时,我会把这个点对C重复加入到我下一次搜索的队列当中。那到底这个方法能不能AC呢?如果那个答案碰巧比较水的话,可能1s内就过了,如果是有点难度的话,可能就要跪了。

然后我也没想到好的方法了,因为我以前接触到的动规都是单线的,用一个二维表就过了的,根本就没往三维四维上面想,这说明“答案范”思想也是有利有弊的。思维的禁锢导致我不可能有更大空间的思考。为了解决上述广搜可能产生的重复问题,dp是必须的了,直到这时我才开始反省我是不是应该往更大胆的方面想象。我还是去看了别人题解,是四维的,有些改善了的是三维,开始我没看懂他们直接四维迭代为什么就能产生正确解,因为不是每一个点对都是可达的(为什么?自己思考下),不管某些点对是不是可达照样算权值,这样难道不会算错嘛?后面我思考了一下,“将错就错”其实也是一种提高速度的方法,因为无需你判断直接执行,节省了步骤自然就快。至于他们这种将错就错能不能算出正确答案我不知道,我从来就不会照搬别人代码。因此我还是按照了自己的思路来,下面贴出代码。

 #include<iostream>
using namespace std; bool IsPoss(int len,int x1,int x2,int M,int N); int main()
{
int M,N;
cin>>M>>N; int**V = new int*[M+];
for(int i=;i<=M;i++)
V[i] = new int[N+]; //获取权值
for(int i=;i<=M;i++)
for(int j=;j<=N;j++)
cin>>V[i][j]; //三维dp数组
int*** A = new int**[M+N-];
for(int i=;i<M+N-;i++)
{
A[i] = new int*[M+];
for(int j=;j<M+;j++)
A[i][j] = new int[M+];
} //初始条件
A[][][] = V[][]+V[][]; for(int i = ;i<M+N-;i++)
{
for(int x1=;x1<=M;x1++)
{
for(int x2=;x2<=M;x2++)
{
if(!IsPoss(i,x1,x2,M,N))
continue;
int min = -(int);
int y1 = i+-x1;
int y2 = i+-x2;
if(x1>&&x2>
&&IsPoss(i-,x1-,x2-,M,N)
&&A[i-][x1-][x2-]>min)
min = A[i-][x1-][x2-];
if(y1>&&y2>
&&IsPoss(i-,x1,x2,M,N)
&&A[i-][x1][x2]>min)
min = A[i-][x1][x2];
if(x1>&&y2>
&&IsPoss(i-,x1-,x2,M,N)
&&A[i-][x1-][x2]>min)
min = A[i-][x1-][x2];
if(x2>&&y1>
&&IsPoss(i-,x1,x2-,M,N)
&&A[i-][x1][x2-]>min)
min = A[i-][x1][x2-];
A[i][x1][x2] = min + V[x1][y1]+V[x2][y2];
}
}
} cout<<A[M+N-][M][M-]<<endl; //释放资源
for(int i=;i<=M;i++)
delete[] V[i];
delete[] V; for(int i=;i<M+N-;i++)
{
for(int j=;j<M+;j++)
delete[] A[i][j];
delete[] A[i];
}
delete[] A;
return ;
} /*
* 用来判断某一个点对是否合法,如果重叠了就不合法,会导致线路交叉的点对也不合法
*/
bool IsPoss(int len,int x1,int x2,int M,int N)
{
int y1 = len+-x1;
int y2 = len+-x2; if(y1<=||y2<=||y1>N||y2>N)
return false; if(x1==x2&&y1==y2)
return false; if(x1<x2&&y1>y2)
return false; return true;
}

思路如下:

转态转移方程:某一步的某一个可达点对的权值 = 前一步中能到达该点对中最大的点对的权值 + 该点对的权值。

那么用四维数组可以表示一个点对的权值:V[x1][y1][x2][y2]。但是假如步数已确定,x也确定,那么y也是唯一确定的,因此可以缩减到三维数组,用V[step][x1][x2]来表示在步数为step时,路线1到达了横坐标为x1,纵坐标为step-x1的点,路线2到达了横坐标为x2,纵坐标为step-x2的点(我以行为横坐标,列为纵坐标)。

由于我怕会混淆出错,我行和列都是从下标1开始迭代的。IsPoss函数用来判断某一个点对是否合法,不合法的直接跳过不计算。

Wikioi 1169 传纸条的更多相关文章

  1. 1169 传纸条 2008年NOIP全国联赛提高组 个人博客:attack.cf

    1169 传纸条 2008年NOIP全国联赛提高组 时间限制: 1 s 空间限制: 128000 KB 题目等级 : 钻石 Diamond         题目描述 Description 小渊和小轩 ...

  2. Codevs 1169 传纸条 2008年NOIP全国联赛提高组

    1169 传纸条 2008年NOIP全国联赛提高组 时间限制: 1 s 空间限制: 128000 KB 题目等级 : 钻石 Diamond 题目描述 Description 小渊和小轩是好朋友也是同班 ...

  3. codevs——1169 传纸条(棋盘DP)

    2008年NOIP全国联赛提高组  时间限制: 1 s  空间限制: 128000 KB  题目等级 : 钻石 Diamond 题解  查看运行结果     题目描述 Description 小渊和小 ...

  4. Codevs 1169 == 洛谷 P1006 传纸条

    ---恢复内容开始--- 1169 传纸条 时间限制: 1 s 空间限制: 128000 KB 题目等级 : 钻石 Diamond 题目描述 Description 小渊和小轩是好朋友也是同班同学,他 ...

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

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

  6. codevs——T1169 传纸条

    http://codevs.cn/problem/1169/  时间限制: 1 s  空间限制: 128000 KB  题目等级 : 钻石 Diamond 题解  查看运行结果     题目描述 De ...

  7. tyvj1011 传纸条

    背景 NOIP2008复赛提高组第三题 描述 小渊和小轩是好朋友也是同班同学,他们在一起总有谈不完的话题.一次素质拓展活动中,班上同学安排做成一个m行n列的矩阵,而小渊和小轩被安排在矩阵对角线的两端, ...

  8. NOIP2008 传纸条

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

  9. NOIP2008传纸条[DP]

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

随机推荐

  1. 详解JavaScript中的Object对象

    Object是在javascript中一个被我们经常使用的类型,而且JS中的所有对象都是继承自Object对象的.虽说我们平时只是简单地使用了Object对象来存储数据,并没有使用到太多其他功能,但是 ...

  2. MySQL 索引优化全攻略

    所谓索引就是为特定的mysql字段进行一些特定的算法排序,比如二叉树的算法和哈希算法,哈希算法是通过建立特征值,然后根据特征值来快速查找.而用的最多,并且是mysql默认的就是二叉树算法 BTREE, ...

  3. 面试时如何优雅的谈论OC

    在面试中,我们经常会遇到一些原理性的问题,很常识但很难用通俗的语言解释清楚,这也是大部分业务级程序员经常失误的地方.虽然写了多年代码,但是核心思想不清,导致自己的后续发展受限,这是一个优秀的程序员和普 ...

  4. [Hapi.js] Up and running

    hapi is a rock solid server framework for Node.js. Its focus on modularity and configuration-over-co ...

  5. Linux 编译安装 apache 2.4

    在安装apache之前需要准备一些必要的依赖包 gcc安装: #yum install -y gcc gcc-c++安装: #yum install gcc-c++  apr安装: 下载包:apr-1 ...

  6. ToString()和Convert.ToString()的区别

    ToString()和Convert.ToString()的区别 一般情况下,这两种方法都可以通用,但是当返回的数据类型中有可能出现null值时如果调用ToString方法了,就会返回NullRefe ...

  7. android 注释常用标签

    javadoc: {@link ActivityGroup}   链接到包.类: {@link #setContentView} 用#链接到类成员: @return View The current ...

  8. VB短信猫开发包,支持超长短信

    一.短信猫开发包(长短信/异步调用)说明:   短信猫开发包以OCX控件的形式提供,支持Windows平台下常用的开发工具:如VB.VB.net.VC++.Power Builder.C#.DELPH ...

  9. JwPlayer播放器【去除Logo、去除版本信息】

    效果图: <html> <head> <title>JwPlayer播放器@杯中红茶</title> <script type="tex ...

  10. rub、sass和compass的安装

    长话短说,直接进入正题. [ruby安装] ruby下载网址:http://rubyinstaller.org/downloads/ 选择适合自己电脑的版本: 下载完成后直接双击安装,记得勾选加入环境 ...