Wikioi 1169 传纸条
这道题是我人生第一道双线动规题,因此我觉得还是很有必要记录下来。
刚接触到这道题的时候我第一反应是单线的动规,可是下一秒我就觉得这样做可能会有问题,因为从左上角(以下简称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 传纸条的更多相关文章
- 1169 传纸条 2008年NOIP全国联赛提高组 个人博客:attack.cf
1169 传纸条 2008年NOIP全国联赛提高组 时间限制: 1 s 空间限制: 128000 KB 题目等级 : 钻石 Diamond 题目描述 Description 小渊和小轩 ...
- Codevs 1169 传纸条 2008年NOIP全国联赛提高组
1169 传纸条 2008年NOIP全国联赛提高组 时间限制: 1 s 空间限制: 128000 KB 题目等级 : 钻石 Diamond 题目描述 Description 小渊和小轩是好朋友也是同班 ...
- codevs——1169 传纸条(棋盘DP)
2008年NOIP全国联赛提高组 时间限制: 1 s 空间限制: 128000 KB 题目等级 : 钻石 Diamond 题解 查看运行结果 题目描述 Description 小渊和小 ...
- Codevs 1169 == 洛谷 P1006 传纸条
---恢复内容开始--- 1169 传纸条 时间限制: 1 s 空间限制: 128000 KB 题目等级 : 钻石 Diamond 题目描述 Description 小渊和小轩是好朋友也是同班同学,他 ...
- CodeVS1169 传纸条 [DP补完计划]
题目传送门 题目描述 Description 小渊和小轩是好朋友也是同班同学,他们在一起总有谈不完的话题.一次素质拓展活动中,班上同学安排做成一个m行n列的矩阵,而小渊和小轩被安排在矩阵对角线的两端, ...
- codevs——T1169 传纸条
http://codevs.cn/problem/1169/ 时间限制: 1 s 空间限制: 128000 KB 题目等级 : 钻石 Diamond 题解 查看运行结果 题目描述 De ...
- tyvj1011 传纸条
背景 NOIP2008复赛提高组第三题 描述 小渊和小轩是好朋友也是同班同学,他们在一起总有谈不完的话题.一次素质拓展活动中,班上同学安排做成一个m行n列的矩阵,而小渊和小轩被安排在矩阵对角线的两端, ...
- NOIP2008 传纸条
题目描述 小渊和小轩是好朋友也是同班同学,他们在一起总有谈不完的话题.一次素质拓展活动中,班上同学安排做成一个m行n列的矩阵,而小渊和小轩被安排在矩阵对角线的两端,因此,他们就无法直接交谈了.幸运的是 ...
- NOIP2008传纸条[DP]
题目描述 小渊和小轩是好朋友也是同班同学,他们在一起总有谈不完的话题.一次素质拓展活动中,班上同学安排做成一个m行n列的矩阵,而小渊和小轩被安排在矩阵对角线的两端,因此,他们就无法直接交谈了.幸运的是 ...
随机推荐
- HDU 1576 A/B(数论)
题目:求(A/B)%9973,但由于A很大,我们只给出n(n=A%9973)(我们给定的A必能被B整除,且gcd(B,9973) = 1).数据给出n和b 推导过程 A/B = K K = 9973* ...
- Hive 5、Hive 的数据类型 和 DDL Data Definition Language)
官方帮助文档:https://cwiki.apache.org/confluence/display/Hive/LanguageManual+DDL Hive的数据类型 -- 扩展数据类型data_t ...
- JavaScript面向对象之类的创建
JavaScript对象的定义: 在js中函数极为对象,对象分为二种:对象字变量产生的对象连接到Object.prototype:函数对象连接到Function.prototype 方法:当一个函数被 ...
- javascript 继承机制设计思想
作者: 阮一峰 原文链接:http://www.ruanyifeng.com/blog/2011/06/designing_ideas_of_inheritance_mechanism_in_java ...
- http://blog.csdn.net/luoshengyang/article/details/6651971
文章转载至CSDN社区罗升阳的安卓之旅,原文地址:http://blog.csdn.net/luoshengyang/article/details/6651971 在Android系统中,提供了独特 ...
- 阿里云部署Docker(5)----管理和公布您的镜像
出到这节,我在百度搜索了一下"阿里云部署Docker",突然发现怎么会有人跟我写的一样呢?哦,原来是其它博客系统的爬虫来抓取,然后也不会写转载自什么什么的.所以,我最终明确为什么那 ...
- 12款 jquery轮播插件
Nivo Slider 首先推荐的这款插件号称世界上最棒的图片轮播插件,有独立的 jQuery 插件和 WordPress 插件两个版本. 目前下载量已经突破 1,800,000 次!jQuery 独 ...
- JS数组追加数组采用push.apply的坑(转)
JS数组追加数组没有现成的函数,这么多年我已经习惯了a.push.apply(a, b);这种自以为很酷的,不需要写for循环的写法,一直也没遇到什么问题,直到今天我要append的b是个很大的数组时 ...
- hbase权威指南学习笔记--过滤器
1.使用hbase是shell客户端进行过滤查询 scan 'testtable',{COLUMNS=>'colfam1:col-0',FILTER=>RowFilter.new(Comp ...
- MVVM模式
MVVM的最大缺点貌似是,报错后不好找, 在安卓6.0的时候出现了一个工具叫做databinding,其中呢主要是用来帮助实现MVVM模式的快速开发 在使用databinding的时候我们需要做的 ...