UVa 116 Unidirectional TSP (DP)
该题是《算法竞赛入门经典(第二版)》的一道例题,难度不算大。我先在没看题解的情况下自己做了一遍,虽然最终通过了,思路与书上的也一样。但比书上的代码复杂了很多,可见自己对问题的处理还是有所欠缺。
该题类似于数字三角形问题,处理的方式就是从倒数第二列逐步推到第一列, 每次选择其后一列权值最小的那条路径。最终找到花费最小的那个即可。由于出现多个答案时要输出字典序考前的路径,所以在选择路径的时候如果出现相同,要选择行数小的那个。我在处理这个问题时用了很多条件语句,使得最终的代码很长。下面是我的代码:
#include <iostream>
#include <cstdio>
#include <cstring> using namespace std; long long a[][];
int pre[][]; int main()
{
int m, n, i, j, temw, temr; while(scanf("%d%d", &m, &n) == )
{
for(i = ; i <= m; i++)
{
for(j = ; j <= n; j++)
{
scanf("%lld", &a[i][j]);
}
}
for(j = n-; j >= ; j--)
{
for(i = ; i <= m; i++)
{
//首先考虑向上方向的路径
if(i == ) //第一行,向上方向走到最后一行
{
temw = a[m][j + ];
temr = m;
}
else
{
temw = a[i - ][j + ];
temr = i - ;
}
//考虑向正前方向的路径
if(a[i][j + ] < temw)
{
temw = a[i][j + ];
temr = i;
}
else if(a[i][j + ] == temw)
{
temr = min(temr, i); //相等取行号小的。
}
//考虑向下方向的路径
if(i == m) //最后一行,向下走到第一行
{
if(a[][j + ] < temw)
{
temw = a[][j + ];
temr = ;
}
else if(a[][j + ] == temw)
{
temr = min(temr, );
}
}
else
{
if(a[i + ][j + ] < temw)
{
temw = a[i + ][j + ];
temr = i + ;
}
else if(a[i + ][j + ] == temw)
{
temr = min(temr, i + );
}
}
a[i][j] += temw;
pre[i][j] = temr; //记录路径
}
}
temw = a[][];
temr = ;
for(i = ; i <= m; i++) //寻找最小的。
{
if(a[i][] < temw)
{
temw = a[i][];
temr = i;
}
}
//输出路径
if(n == )
{
printf("%d\n", temr);
}
else
{
for(i = temr, j = ; j <= n-;)
{
printf("%d ", i);
i = pre[i][j];
j++;
}
printf("%d\n", i);
}
printf("%lld\n", a[temr][]);
}
return ;
}
显然,在处理三个方向时,用了很多代码,而书上是这样做的:
int rows[] = {i, i-, i+}; //普通情况下的行号
if(i == ) //书上第一行行号为0,如果是第一行,向上的行号需要改变。
rows[] = m - ; //最后一列列号为m-1
if(i == m-)
rows[] = ;
d[i][j] = INF; //数组d用来存储权值
sort(rows, rows+); //先排序,再比较
for(int k = ; k < ; k++)
{
int v = d[rows[k]][j+] + a[i][j];
if(v < d[i][j])
{
d[i][j] = v;
next[i][j] = rows[k];
}
}
显然,书上通过先排序再比较,这样从最小的行号开始,找最小权值,找到的最小权值一定是行号最小的,减小了很多代码量。
还需要说的一点是,这道题我一开始看错了题意!!!这是比赛的大忌! 根据所给的图,想当然地以为是从第一行第一列开始走到最后一行最后一列。顺便说一下这种情况的我的思路吧。这种情况下,需要一个bool型数组标记每个点是否可到达,首先标记终点可到达,然后从倒数第二列循环,选择后一列中可以到达且权值最小,行号最小的一条路径,并标记该点可到达,如果后面没有可到达的点,就标记该点不可到达。循环到第一列时,只需要考虑起点即可。其他类似于原题。
UVa 116 Unidirectional TSP (DP)的更多相关文章
- UVA 116 Unidirectional TSP(dp + 数塔问题)
Unidirectional TSP Background Problems that require minimum paths through some domain appear in ma ...
- UVA 116 Unidirectional TSP(DP最短路字典序)
Description Unidirectional TSP Background Problems that require minimum paths through some domai ...
- uva 116 Unidirectional TSP (DP)
uva 116 Unidirectional TSP Background Problems that require minimum paths through some domain appear ...
- uva 116 Unidirectional TSP【号码塔+打印路径】
主题: uva 116 Unidirectional TSP 意甲冠军:给定一个矩阵,当前格儿童值三个方向回格最小值和当前的和,就第一列的最小值并打印路径(同样则去字典序最小的). 分析:刚開始想错了 ...
- UVA 116 Unidirectional TSP 经典dp题
题意:找最短路,知道三种行走方式,给出图,求出一条从左边到右边的最短路,且字典序最小. 用dp记忆化搜索的思想来考虑是思路很清晰的,但是困难在如何求出字典序最小的路. 因为左边到右边的字典序最小就必须 ...
- UVA - 116 Unidirectional TSP 多段图的最短路 dp
题意 略 分析 因为字典序最小,所以从后面的列递推,每次对上一列的三个方向的行排序就能确保,数字之和最小DP就完事了 代码 因为有个地方数组名next和里面本身的某个东西冲突了,所以编译错了,后来改成 ...
- UVa - 116 - Unidirectional TSP
Background Problems that require minimum paths through some domain appear in many different areas of ...
- uva 116 - Unidirectional TSP (动态规划)
第一次做动规题目,下面均为个人理解以及个人方法,状态转移方程以及状态的定义也是依据个人理解.请过路大神不吝赐教. 状态:每一列的每个数[ i ][ j ]都是一个状态: 然后定义状态[ i ][ j ...
- UVA - 116 Unidirectional TSP (单向TSP)(dp---多段图的最短路)
题意:给一个m行n列(m<=10, n<=100)的整数矩阵,从第一列任何一个位置出发每次往右,右上或右下走一格,最终到达最后一列.要求经过的整数之和最小.第一行的上一行是最后一行,最后一 ...
随机推荐
- Unity UGUI 使用 CCTween 实现 打字效果
最近闲来无事 就研究了下 打字效果的实现 结果发现很简单 直白了说是太简单了 下边效果图加代码 走着 增加可拖拽 脚本 (场景物体不支持 alpha 隐藏) 目前 CCAnim 封装了 move R ...
- Jquery弹窗插件Lhgdialog的用法
Lhgdialog的用法 大家都知道用js可以实现,但是在使用js实现的弹窗时得考虑很东西:浏览器的兼容.页面的交互等等问题. 在这里简单介绍一下lhgdialog的用法. 参数有: Title:弹窗 ...
- javaScript滚动新闻之上下左右平滑滚动
<!DOCTYPE HTML> <html> <head> <meta http-equiv="Content-Type" content ...
- oracle数据库导出并重新导入
斌斌 (给我写信) 原创博文(http://blog.csdn.net/binbinxyz),转载请注明出处! 一.导出数据库 1.将数据库TEST完全导出,用户名scott密码tiger,导出到D: ...
- ASP.NET Web API Authorization using Tokens
Planning real world REST API http://blog.developers.ba/post/2012/03/03/ASPNET-Web-API-Authorization- ...
- mybatisnet轻量级ORM框架
https://code.google.com/p/mybatisnet/source/checkout http://blog.csdn.net/arvinstudy/article/details ...
- M记单刷鸡盒副本
今天去M记单刷鸡盒副本,听说此副本掉落最新道具:黑暗之门.鸡翅区和鸡块区全通无压力,鸡腿区难度最大,老一是个灭团点.现在肚子很难受,刚去厕所吐了一把,看来有点高估自己,此副本最好还是组队前往,单刷压力 ...
- Linux下Oracle常见安装错误[Z]
#./runInstaller之后出现如下的错误信息: RedHat AS5 x86上安装Oracle1020 Exception in thread "main" java.la ...
- 学习Javascript DOM 编程艺术的一点心得
最近又看了一遍JS DOM编程艺术,照例来写一写读后感. 其实,我从中学到最深的是几个概念:1.平稳退化.当浏览器并不支持JS的时候网页的基本核心功能是还可以用的:2.逐渐增强.在原始的信息层上用其他 ...
- linux创建用户和组
linux下创建用户(一) Linux 系统是一个多用户多任务的分时操作系统,任何一个要使用系统资源的用户,都必须首先向系统管理员申请一个账号,然后以这个账号的身份进入系统.用户的账号一方面可以帮助系 ...