探寻宝藏_动态规划和路径遍历
问题描述
传说HMH大沙漠中有一个M*N迷宫,里面藏有许多宝物。某天,Dr.Kong找到了迷宫的地图,他发现迷宫内处处有宝物,最珍贵的宝物就藏在右下角,迷宫的进出口在左上角。当然,迷宫中的通路不是平坦的,到处都是陷阱。Dr.Kong决定让他的机器人卡多去探险。
但机器人卡多从左上角走到右下角时,只会向下走或者向右走。从右下角往回走到左上角时,只会向上走或者向左走,而且卡多不走回头路。(即:一个点最多经过一次)。当然卡多顺手也拿走沿路的每个宝物。
Dr.Kong希望他的机器人卡多尽量多地带出宝物。请你编写程序,帮助Dr.Kong计算一下,卡多最多能带出多少宝物。
输入
第一行: K 表示有多少组测试数据。
接下来对每组测试数据:
第1行: M N
第2~M+1行: Ai1 Ai2 ……AiN (i=1,…..,m)
【约束条件】
2≤k≤5 1≤M, N≤50 0≤Aij≤100 (i=1,….,M; j=1,…,N)
所有数据都是整数。 数据之间有一个空格。
输出
对于每组测试数据,输出一行:机器人卡多携带出最多价值的宝物数
样例输入
2
2 3
0 10 10
10 10 80
3 3
0 3 9
2 8 5
5 7 100
样例输出
120
134
问题简单描述

如图简单所示,在类似红蓝标记的这样(过左上角(起点)和右下角(最深处)并且无交叉)的所有可能的回路中找到一条能使路过的位置的权值(宝藏价值)之和最大的回路并能输出其权值之和,这个问题就算解决了
由于卡多走路的方式所限:回路的任意一单位段的连接必须满足只有上下相邻或左右相邻的点间可连接的条件
解决方法
动态规划法
这是双进程DP问题,首先,假设出发点为A 终点为B 那么,根据题目给出的条件,可以推出A->B的动态转移方程
为 dp[i][j] = max(dp[i-1][j],dp[i][j-1]) + a[i][j]; 由于,同理可得B的情况,那么,题目的意思是A->B
然后 B -> A我们可以假设同时从A点出发,得到两条不同路径,这个是一样的效果。所以,我们可以得到一个动
态转移方程
dp[i][j][p][q] = max(dp[i-1][j][p-1][q],dp[i-1][j][p][q-1],dp[i][j-1][p-1][q],dp[i][j-1][p][q-1])+
ma[i][j] + ma[p][q]
因为 每次只能移动一步,即 i+1 或j+1 那么 i+j是移动的步数 因为从A点开始移动的,经过相同的步数,肯
定能得到i+j = p+q,还有一点要注意一下,这题与NYOJ 61是同类问题,但是,有一点细节要注意,最后终点的
值也要算上,上面的动态方程得到的值不包含两个A 和 B的值,因为A是起点,所以,他的值一般是0,所以,得
到最后的结果应该是
sum = max(dp[m-1][n][m-1][n],dp[m-1][n][m][n-1],dp[m][n-1][m-1][n],dp[m][n-1][m][n-1]) + ma[m][n]

DFS(深度优先搜索:针对路径而非结点)
深度优先搜索(根据卡多走路的规则,即只能向下或向右走可确定结点间的可达关系),这样可以轻松地将从入口到右下角所有的路径遍历出来,定义路径对象的类,保存每一条路径,因为卡多的路径是来回两个的,所以两类对象两两组合,根据组合的路径的宝物总价值对组合进行排序,选出宝物总价值最大且路径不冲突的组合作为结果即可。

BFS(广度优先搜索:针对路径而非结点)
广度优先搜索(类似动态规划的过程,双进程进行,从入口同时出发不相交的两条路径作为卡多的来回两条路径,广度优先的方便之处是可以在相同步数的层次内继承上一层次的结果根据卡多走路的规则和不相交的约束可以快速确定走到此层次的所有路径)出所有的路径,由队列来动态存储,由于是双进程,此时遍历出的路径就是一个回路,卡多来回的路径,因此只需要选出宝物总价值最大的路径即可,便可得出最终的结果。


给出代码
动态规划(DP):可视化库graphics
1 | |
深度优先搜索(DFS)
OneRoad.h
1 | |
OneRoad.cpp
1 | |
main.cpp
1 | |
广度优先搜索(BFS)
1 | |
请评论
所有代码已经细致地进行过调试,请放心使用,思路和功能确保正确,但实现的手段略显拙劣,请提出你改进的建议,感激不尽。