帮助:图形竞赛问题:可能是修改后的Dijkstra或其他替代算法

时间:2010-04-13 02:24:32

标签: java c algorithm graph

我正在尝试关于图表的比赛练习:

XPTO是一个勇敢的冒险家(对他自己的好处来说有点过于苛刻),他吹嘘探索宇宙的每个角落,无论多么荒凉。事实上,他并没有访问人们可以轻松居住的行星,他更喜欢那些只有一个疯子会有很好理由去的地方(例如几百万个学分)。他的最新攻击是试图在Proxima III中生存。问题是Proxima III遭受高腐蚀性酸的风暴,这些酸会破坏一切,包括专门设计用来抵抗腐蚀的太空服。

我们这位勇猛的探险家被发现在这些风暴之中的一个长方形区域。幸运的是,他有一种仪器能够测量每个扇区上酸的精确浓度以及它对太空服的损害程度。现在,他只需要知道他是否能逃脱风暴。 的问题

问题在于找到一条允许XPTO逃离有害风暴的逃生路线。你将获得太空服的初始能量,矩形区域的大小以及太空服在站在每个区域时所遭受的伤害。

你的任务是找到退出扇区,到达它所需的步数以及他的套装离开矩形区域时的能量。选择的逃生路线应该是最安全的(即,他的宇航服将受损最少)。请注意,如果他的西装的能量达到零,XPTO将会灭亡。

如果有多个可能的解决方案,请选择使用最少步骤的解决方案。如果存在至少两个具有相同步数(X1,Y1)和(X2,Y2)的扇区,则选择第一个如果X1 <1。 X2或者如果X1 = X2且Y1

约束 0&lt; E≤30000套装的起始能量
0≤W≤500矩形的宽度
0≤H≤500矩形高度
0&lt; X&lt; W起始位置为
0&lt; Y&lt; H起始Y位置
0≤D≤10000每个部门受到的损害

输入

给出的第一个数字是测试用例的数量。每个案例将由一个整数为E,X和Y的行组成。下一行将包含整数W和H.以下行将保存包含太空服在相应扇区中将遭受的损害D的矩阵。请注意,与计算机爱好者的情况一样,(1,1)对应于左上角。

输出

如果有解决方案,输出将是剩余能量,出口扇区的X和Y坐标以及将导致Rodericus安全的路线的步数。如果没有解决方案,这句话再见残酷的世界!将写。

示例输入

3
40 3 3  
7 8  
12 11 12 11  3 12 12  
12 11 11 12  2  1 13  
11 11 12  2 13  2 14  
10 11 13  3  2  1 12 
10 11 13 13 11 12 13 
12 12 11 13 11 13 12  
13 12 12 11 11 11 11  
13 13 10 10 13 11 12  
8 3 4  
7 6 
4  3  3  2  2  3  2  
2  5  2  2  2  3  3  
2  1  2  2  3  2  2  
4  3  3  2  2  4  1  
3  1  4  3  2  3  1  
2  2  3  3  0  3  4  
10 3 4  
7 6  
3  3  1  2  2  1  0 
2  2  2  4  2  2  5  
2  2  1  3  0  2  2  
2  2  1  3  3  4  2  
3  4  4  3  1  1  3  
1  2  2  4  2  2  1 

示例输出

12 5 1 8  
Goodbye cruel world!  
5 1 4 2

基本上,我认为我们必须做一个改进的Dijkstra,其中节点之间的距离是套装的能量(我们必须减去它而不是像距离那样正常的总和),步骤是......沿着小路走的。带有bester二项式(能量,num_Steps)的pos是我们的“出路”。

重要提示:XPTO显然无法移动对角线,因此我们不得不削减这种情况。

我有很多想法,但实施它们时遇到了这样的问题......

有人可以帮助我用一些代码或至少是想法来思考这个问题吗?

我完全错了吗?

2 个答案:

答案 0 :(得分:1)

您不必像对待任何非常规转换一样处理此问题(减去而不是添加等)。

从一个节点到另一个节点的最短路径可以最大限度地减少沿途对套装的总伤害,无论此行程是否会扼杀你。

找到从START到EXIT的最短路径,按照通常的Dijkstra方法总结边缘权重,然后考虑这条最短路径是否适用于给定的套装功率。如果不是,那么Goodbye cruel world!

如果你坚持修剪搜索一旦你知道你肯定没有到达EXIT,那么在上述实施之后添加它是微不足道的:因为你正在扩展你的Dijkstra的搜索范围搜索,如果即使前往下一个最接近的节点进行扩展就会杀死你,那么搜索空间的其余部分也会,所以你可以中止并Goodbye cruel world!

至于图表本身,概念上这就是你想要的。有向图的顶点由网格中的所有节点和一个人工EXIT节点组成。

  • 所有边缘节点都有一个指向EXIT的边缘;这些边缘的重量为0
  • 所有相邻(非对角线)节点在它们之间具有有向边
    • 从节点n1n2,边缘的权重(即从n1n2旅行的成本损失)是留在节点时造成的损失n2(我们称之为damageAt[n2],您可以在输入中使用D矩阵。

因此,从START到EXIT必须维持的最小伤害总数为damageAt[START] + costOf(shortestPathBetween(START, EXIT))

总之,这种方法:

  • 仅需要标准Dijkstra实施
  • 只需要很小的修改即可添加修剪
  • 只需要从输入网格到有向图的非常简单的转换

答案 1 :(得分:1)

由于这是一个竞赛问题,我只是给出一个小提示:

在此示例中,节点具有权重,而不是边缘。将这样的图转换为通常类的一种方法是用两个节点替换每个节点,in节点和out节点,以及从in到{{1}的有向边权重等于原始节点的权重。然后,对于原始图中的每个有向边,将有向边从一个out节点放到下一个out节点。

你的想法听起来不错 - 顺其自然。

顺便说一句,在处理这些问题时,请尝试自己完成实现。 很少有助于简单地看到其他人的实现。如果需要,请求有关算法的帮助,但请自行实施。