题目链接: https://uva.onlinejudge.org/index.php?option=com_onlinejudge&Itemid=8&category=3&page=show_problem&problem=52

  题目描述: 一个整数矩阵, 求第一列到最后一列的最小整数和, 只能从第一列出发向右, 右下, 右上走, 第一行的上一行是第m行,第m行的下一行是第一行, 打印出字典序最小方案

  解题思路: 很简单的一个DP, 状态很容易设计, dp(i, j)表示从格子a(i, j)出发到最后一列的最小开销, dp(i, j) = min( dp(i-1, j+1), dp(i, j+1), dp(i+1, j+1) ), 其中有一些细节需要注意, 具体在代码中实现

  代码: 这是我的错误代码, 只能够过得掉样例....打印路径难道我了......怎么说也搞了一年了啊.....真的菜

#include <iostream>
#include <cstdio>
#include <string>
#include <vector>
#include <map>
#include <cstring>
#include <iterator>
#include <cmath>
#include <stack>
using namespace std;int a[15][105]; //
int dp[15][105]; // dp(i, j) 表示以从第一行出发a(i, j)为结尾的最短距离
const int INF = 0x3fffffff;
int past[15][105]; // -1 a[i][j]上个点是a[i-1][j] 0......1......
stack<int> S;int main() {int m, n;while( ~scanf( "%d%d", &m, &n ) ) {for( int i = 1; i <= m; i++ ) {for( int j = 1; j <= n; j++ ) {scanf( "%d", &a[i][j] );if( j == 1 ) dp[i][j] = a[i][j];else dp[i][j] = INF;}}memset(past, 0, sizeof(past));
//        for( int i = 1; i <= m; i++ ) {
//            past[i][1] = INF;
//        }for( int j = 2; j <= n; j++ ) {for( int i = 1; i <= m; i++ ) {dp[i][j] = dp[i][j-1]+a[i][j];if( i > 1 ) {if( dp[i-1][j-1]+a[i][j] <= dp[i][j] ) {dp[i][j] = dp[i-1][j-1]+a[i][j];past[i][j] = -1;}}else {if( dp[m][j-1]+a[i][j] < dp[i][j] ) {dp[i][j] = dp[m][j-1]+a[i][j];past[i][j] = -1;}}
//                if( i == 1 && j == 3 ) cout << "==" << dp[i][j] << endl;if( i < m ) {
//                    if( i == 1 && j == 3 ) cout << "==" << dp[i+1][j-1] << " " << a[i][j] << endl;if( dp[i+1][j-1]+a[i][j] < dp[i][j] ) {dp[i][j] = dp[i+1][j-1]+a[i][j];past[i][j] = 1;}}else {if( dp[1][j-1]+a[i][j] <= dp[i][j] ) {dp[i][j] = dp[1][j-1]+a[i][j];past[i][j] = 1;}}}}
//        for( int i = 1; i <= m; i++ ) {
//            for( int j = 1;j <= n; j++ ) {
//                cout << dp[i][j] << " ";
//            }
//            cout << endl;
//        }int ans = INF;int index = -1;for( int i = 1; i <= m; i++ ) {if( dp[i][n] < ans ) {ans = dp[i][n];index = i;}}S.push(index);for( int i = n; i > 1; i-- ) {if( past[index][i] == 0 ) {S.push(index);}else if( past[index][i] == -1 ) {if( index == 1 ) {S.push(index = m);}else {S.push(--index);}}else {if( index == m ) {S.push(index = 1);}else {S.push(++index);}}}while( !S.empty() ) {if( (int)S.size() == 1 ) printf( "%d", S.top() );else {printf( "%d ", S.top() );}S.pop();}printf( "\n" );printf( "%d\n", ans );}return 0;
}

View Code

  AC 代码

#include <iostream>
#include <cstdio>
#include <string>
#include <vector>
#include <map>
#include <cstring>
#include <iterator>
#include <cmath>
#include <algorithm>
#include <stack>
using namespace std;int d[15][150]; // d[i][j] means 以a[i][j]为起点到最后一列的最短距离
int a[15][150];
int nextt[15][150]; // a[i][j] 下一个点是第next[i][j]行
const int INF = 0x3fffffff;int main() {int m, n;while( ~scanf( "%d%d", &m, &n ) ) {for( int i = 0; i < m; i++ ) {for( int j = 0; j < n; j++ ) {scanf( "%d", &a[i][j] );}}int ans = INF;int first = 0;for( int j = n-1; j >= 0; j-- ) {for( int i = 0; i < m; i++ ) {if( j == n-1 ) d[i][j] = a[i][j]; // 边界else {int rows[3] = { i, i-1, i+1 };if( i == 0 ) rows[1] = m-1;if( i == m-1 ) rows[2] = 0;sort( rows, rows+3 );d[i][j] = INF;for( int k = 0; k < 3; k++ ) {int temp = d[rows[k]][j+1] + a[i][j];if( temp < d[i][j] ) {d[i][j] = temp;nextt[i][j] = rows[k];}}}}}
//        for( int i = 0; i < m; i++ ) {
//            for( int j = 0; j < n; j++ ) {
//                cout << d[i][j] << " ";
//            }
//            cout << endl;
//        }for( int i = 0; i < m; i++ ) {if( d[i][0] < ans ) {ans = d[i][0];first = i;}}printf( "%d", first+1 );for( int i = nextt[first][0], j = 1; j < n; i = nextt[i][j], j++ ) {printf( " %d", i+1 );}printf( "\n" );printf( "%d\n", ans );}return 0;
}

View Code

  思考: 本来是一道简单的DP题, 自己却写了一上午, 主要收获如下, 在要求打印路径的时候就要注意设计的状态应该是以dp[i][j]为起点, 不然会有一些BUG, 比如上面的错误代码, 还有一点很重要一点就是: 如果用数组迭代的话, 要保证在计算d[i][j] 时候, 你后面的状态转移设计到的式子全部已经有值........这点非常重要, 因为动态规划应该满足最优子结构, 也就是说, 子结构的值我应该知道, 如果想要倒过来求的话, (边界值在一边, 开始计算在另一边)就应该用到函数递归(记忆化搜索), 其实可以说的数组迭代就是递归的一部分(函数到底后反过来求值那一段。) 自己还是不熟啊, 为了区域赛能拿牌! 加紧练习!

转载于:https://www.cnblogs.com/FriskyPuppy/p/7272994.html

UVA 116 Unidirectional TSP DP相关推荐

  1. UVA 116 Unidirectional TSP (白书dp)

    http://acm.hust.edu.cn:8080/judge/problem/viewProblem.action?id=18206 1 /* 2 题目大意: 3 从第一列的任意一格出发,到子最 ...

  2. UVA 116——Unidirectional TSP

    题意:给定一个n*m的矩阵,从第一列任意位置向右,右下,右上走一格,可以循环,要求经过的数字的和最小. 思路:记忆化搜索.每次有三个状态,从这三个状态中选择出最优的一个,然后状态累加,保存路径. co ...

  3. Unidirectional TSP—dp

    问题描述: Problems that require minimum paths through some domain appear in many different areas of comp ...

  4. Unidirectional TSP UVA - 116(多阶段决策+输出字典序最小的路径)

    Unidirectional TSP UVA - 116 题意: 给你m行n列的矩阵,从第一列出发,到最后一列. 要求 经过的整数和最小. 输出路径上,每列的行号,多解时,输出字典序最小的. 思路: ...

  5. UVa 116 (多段图的最短路) Unidirectional TSP

    题意: 有一个m行n列的正整数环形矩阵(即矩阵第一行的上一行是最后一行,最后一行的下一行是第一行),从第一列的任意位置出发,每次只能向右,右上,右下三个方向行走,输出路径及路径上所有数之和的最大值,多 ...

  6. 单向TSP问题(Uva 116)

    题意:就是给你一个图 让你从第一列开始走到最后一列 寻找最小的路径,然后这一题难点在于 路径的记录以及第一行跟最后一行联通 最后一行跟第一行也是联通的 题目传送门 代码如下,紫书讲的很好了我就不写分析 ...

  7. UVA116 单向TSP Unidirectional TSP(多阶段决策问题、输出字典序最小的方案、DAG上DP)

    整理的算法模板合集: ACM模板 题目传送门 简单的多阶段决策问题. 多段图DAG,其节点可以划分为若干个阶段,每一个阶段只由上一个阶段所决定. 因为本题要求输出从前到后的方案,所以我们转移方程的时候 ...

  8. UVA 1331 Minimax Triangulation DP, 三角剖分

    题目链接: https://uva.onlinejudge.org/index.php?option=com_onlinejudge&Itemid=8&page=show_proble ...

  9. uva 10453 - Make Palindrome(dp)

    题目链接:10453 - Make Palindrome 题目大意:给出一个字符串,通过插入字符使得原字符串变成一个回文串,要求插入的字符个数最小,并且输出最后生成的回文串. 解题思路:和uva 10 ...

最新文章

  1. Blazor将.NET带回到浏览器
  2. 用GO把你想说的话写到比特币链上
  3. MapReduce Java API实例-统计平均成绩
  4. 【译】Hard Forks, Soft Forks, Defaults and Coercion
  5. 《c语言从入门到精通》看书笔记——第11章 结构体和共用体
  6. UIScrollViewDelegate-代理API详解
  7. 没人可以通过勤劳工作发财致富
  8. Atitit php读取数据库记录集合并循环修改展示//------------------------ini db sys$dbstr = “mysql:host=“ . $mysql_con
  9. 一元多项式的乘法与加法运算_如果加法变成【乘法】 , 那么什么能变成【加法】 ? ——记一则函数方程...
  10. ffmpeg 音乐循环_背景音乐自动循环播放
  11. 为什么人人都应该学编程?
  12. STM32+DWM1000开发uwb测距系列教程之二:源码分析及源码移植(基于STM32 cubemx+keil MDK)
  13. matlab gui设置参数,基于Matlab/GUI界面设计的参数在线整定与优化(三)
  14. 电脑恶意软件删除方法
  15. python三维图旋转_python中的三维图像旋转
  16. 【管理】需求分析与软件设计|需求分析报告和需求规格说明书的区别
  17. 第十七届智能车竞赛英飞凌 | 逐飞联合直播-平衡单车组入门讲解
  18. 机器学习 使用三分法找最优解参数
  19. 【Maven】Archetype
  20. 随笔之看雷军视频有感//2021-2-24

热门文章

  1. hdu3368 Reversi
  2. DataGrid入门经典(C#)
  3. 服务器架设笔记——Apache模块开发基础知识
  4. Caffe中对cifar10执行train操作
  5. 一维码EAN 8简介及其解码实现(zxing-cpp)
  6. python信用卡违约_Python信用卡验证
  7. python re match groups_python re.match与re.search的区别
  8. android profiler 简书,使用AndroidStudio提供的Android Profiler工具和mat进行内存泄漏分析...
  9. sftp shell 批量上传文件_Shell自动上传下载文件到SFTP服务器
  10. linux那个11命令是什么意思,11个有用的Linux命令