该题是《算法竞赛入门经典(第二版)》的一道例题,难度不算大。我先在没看题解的情况下自己做了一遍,虽然最终通过了,思路与书上的也一样。但比书上的代码复杂了很多,可见自己对问题的处理还是有所欠缺。

  该题类似于数字三角形问题,处理的方式就是从倒数第二列逐步推到第一列, 每次选择其后一列权值最小的那条路径。最终找到花费最小的那个即可。由于出现多个答案时要输出字典序考前的路径,所以在选择路径的时候如果出现相同,要选择行数小的那个。我在处理这个问题时用了很多条件语句,使得最终的代码很长。下面是我的代码:

  

 #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)的更多相关文章

  1. UVA 116 Unidirectional TSP(dp + 数塔问题)

     Unidirectional TSP  Background Problems that require minimum paths through some domain appear in ma ...

  2. UVA 116 Unidirectional TSP(DP最短路字典序)

    Description    Unidirectional TSP  Background Problems that require minimum paths through some domai ...

  3. uva 116 Unidirectional TSP (DP)

    uva 116 Unidirectional TSP Background Problems that require minimum paths through some domain appear ...

  4. uva 116 Unidirectional TSP【号码塔+打印路径】

    主题: uva 116 Unidirectional TSP 意甲冠军:给定一个矩阵,当前格儿童值三个方向回格最小值和当前的和,就第一列的最小值并打印路径(同样则去字典序最小的). 分析:刚開始想错了 ...

  5. UVA 116 Unidirectional TSP 经典dp题

    题意:找最短路,知道三种行走方式,给出图,求出一条从左边到右边的最短路,且字典序最小. 用dp记忆化搜索的思想来考虑是思路很清晰的,但是困难在如何求出字典序最小的路. 因为左边到右边的字典序最小就必须 ...

  6. UVA - 116 Unidirectional TSP 多段图的最短路 dp

    题意 略 分析 因为字典序最小,所以从后面的列递推,每次对上一列的三个方向的行排序就能确保,数字之和最小DP就完事了 代码 因为有个地方数组名next和里面本身的某个东西冲突了,所以编译错了,后来改成 ...

  7. UVa - 116 - Unidirectional TSP

    Background Problems that require minimum paths through some domain appear in many different areas of ...

  8. uva 116 - Unidirectional TSP (动态规划)

    第一次做动规题目,下面均为个人理解以及个人方法,状态转移方程以及状态的定义也是依据个人理解.请过路大神不吝赐教. 状态:每一列的每个数[ i ][ j ]都是一个状态: 然后定义状态[ i ][ j ...

  9. UVA - 116 Unidirectional TSP (单向TSP)(dp---多段图的最短路)

    题意:给一个m行n列(m<=10, n<=100)的整数矩阵,从第一列任何一个位置出发每次往右,右上或右下走一格,最终到达最后一列.要求经过的整数之和最小.第一行的上一行是最后一行,最后一 ...

随机推荐

  1. localStorage点击次数存储

    <!DOCTYPE html><html><head><meta charset="utf-8"> <title>菜鸟教 ...

  2. android 自定义ViewGroup和对view进行切图动画实现滑动菜单SlidingMenu[转]

    http://blog.csdn.net/jj120522/article/details/8095852 示意图就不展示了,和上一节的一样,滑动菜单SlidingMenu效果如何大家都比较熟悉,在这 ...

  3. DOM注意事项(八):JavaScript操作环境和垃圾收集

    一.运行环境 在约JavaScript对象或this当指向问题,念就是运行环境.即上下文环境.运行环境在JavaScript是一个非常重要的概念.由于它定义了变量或函数有权訪问的其他数据,决定了它们各 ...

  4. 常用的sql server规范

    常见的字段类型选择1.字符类型建议采用varchar/nvarchar数据类型2.金额货币建议采用money数据类型3.科学计数建议采用numeric数据类型4. 自增长标识建议采用bigint数据类 ...

  5. AngularJs 实例

    1.AngularJs 表单验证: 示例 .controller('signupController', ['$scope', function($scope) { $scope.submitted ...

  6. JAVA 堆设置

    JAVA 堆设置 第四节 堆已经讲得差不多啦,这章我们以一个例子来说说如何设置以及当发生堆溢出的时候怎么排查问题.先看一小段代码:         代码中使用了一个无限循环来为list添加对象,如果采 ...

  7. 对于windows窗口的标题菜单栏的操作——删除/禁用 最小最大话和关闭

    HWND hand = FindWindow(NULL, "计算器"); int nStyle = GetWindowLong(hand, GWL_STYLE);nStyle &a ...

  8. error C4996 The POSIX name for this item is deprecated. Instead, use the ISO C and C++ conformant name

    error C4996: 'strupr': The POSIX name for this item is deprecated. Instead, use the ISO C and C++ co ...

  9. Hive进阶(上)

    Hive进阶(上) Hive进阶(上) 执行数据导入 使用Load语句 语法: 1.LOAD DATA [LOCAL] INPATH 'filepath' [OVERWRITE] INTO TABLE ...

  10. 数据库课本SQL第三章答案

    3 .用 sQL 语句建立第二章习题 5 中的 4 个表. 答: 对于 S 表: S ( SNO , SNAME , STATUS , CITY ) ; 建 S 表: CREATE TABLE S ( ...