丢失的典当问题


14

丢失的典当问题

象棋比赛结束后,幸存的棋子被留在了敌后。让我们帮助他找到回家的最短途路。

最初的问题描述了nXn“棋盘”板以及f: {1,..,n-1}X{1,..,n}X{-1,0,1} => R+权重的函数。目标是找到一条最佳路径,从对接线中的某个正方形到顶线中的其他正方形,其中可能的移动是:左上,上,右上,并且您可能不退出木板。

这个问题相对容易使用动态编程在O(n ^ 2)中解决,但这是代码高尔夫,我们不在乎诸如运行时复杂性之类的无用的东西。

问题

输入:一个3维数组(或您选择的其他集合,通过stdin接收,或作为函数参数接收),对应于常规棋盘,大小完全相同:7X8X3(#linePasses X #rowSize X #movesPerPass)包含非负整数。的移动花费一些位置(i,j),其中i是行索引,并且j是列指数,分别是:

  • a[i][j][0]从左上角到正方形(i+1,j-1)或以图形方式显示的费用:\
  • a[i][j][1]到达正方形(i+1,j)或以图形方式显示的费用:|
  • a[i][j][2]垂直移动到正方形(i+1,j+1)或以图形方式移动的费用:/

您可能会假设它不包含总和大于的路径MAX_INT

输出:显示最佳(最短,即最小权重之和)路径的8X8 ASCII输出(如果有超过1个最佳结果,则可以显示您选择的任意路径)。路径是从下到上绘制的,在每一行中,与典当在路径中的位置相对应的字符是它要创建的字符。例如,如果棋子要从第3列向左移动(移至第2列),则应绘制:

#?######
##\#####

在哪里?应该替换为下一步。最终职位需要画成X

例子

输入:

[
  [[1,1,1],[1,1,1],[0,1,1],[1,1,1],[1,1,1],[1,1,1],[1,1,1],[1,1,1]],
  [[1,1,1],[1,0,1],[1,1,1],[1,1,1],[1,1,1],[1,1,1],[1,1,1],[1,1,1]],
  [[1,1,1],[1,1,0],[1,1,1],[1,1,1],[1,1,1],[1,1,1],[1,1,1],[1,1,1]],
  [[1,1,1],[1,1,1],[1,1,0],[1,1,1],[1,1,1],[1,1,1],[1,1,1],[1,1,1]],
  [[1,1,1],[1,1,1],[1,1,1],[1,0,1],[1,1,1],[1,1,1],[1,1,1],[1,1,1]],
  [[1,1,1],[1,1,1],[1,1,1],[1,0,1],[1,1,1],[1,1,1],[1,1,1],[1,1,1]],
  [[1,1,1],[1,1,1],[1,1,1],[0,1,1],[1,1,1],[1,1,1],[1,1,1],[1,1,1]]
]

输出:

##X#####
###\####
###|####
###|####
##/#####
#/######
#|######
##\#####

输入:

[
  [[41,27,38],[12,83,32],[50,53,35],[46,32,26],[55,89,82],[75,30,87],[2,11,64],[8,55,22]],
  [[56,21,0],[83,25,38],[43,75,63],[56,60,77],[68,55,89],[99,48,67],[94,30,9],[62,62,58]],
  [[23,18,40],[24,47,61],[96,45,72],[71,6,48],[75,63,98],[93,56,51],[23,31,30],[49,34,99]],
  [[20,47,42],[62,79,72],[32,28,44],[68,61,55],[62,39,57],[4,17,49],[97,85,6],[91,18,12]],
  [[51,50,11],[32,39,56],[12,82,23],[33,88,87],[60,55,22],[29,78,14],[70,11,42],[63,94,67]],
  [[75,64,60],[27,79,86],[70,72,56],[55,45,32],[95,67,12],[87,93,98],[81,36,53],[38,22,93]],
  [[31,80,50],[77,71,22],[59,46,86],[64,71,53],[41,19,95],[62,71,22],[92,80,41],[26,74,29]]
]

输出:

######X#
#####/##
####/###
#####\##
#####|##
######\#
######|#
#######\

这是,因此最短的代码获胜。

公平竞赛。没有漏洞...

编辑:

在scala中写了一个简单的解决方案,您可以看一下。还有一个可以在线使用Scala代码播放的站点:scalakata(只需将要点复制并粘贴到scalakata,然后点击“播放”按钮)

Answers:


5

Q:199字节

f:{m::x;n::{@/[+/-1 0 1_\:/:(x;m[y;;|!3]);0 2;(0W,),{x,0W}]};i:*<*|r:{&/n[x;y]}\[8#0;!7];  s:{-1+{*<x}'+n[y;z]}\[();(,8#0),-1_r;!7];j:i,{x+y x}\[i;|s];-1(@[8#"#";;:;]'[j;"X","/|\\"1+s'[|!7;-1_j]]);}

笔记

  • Q解释器(kx.com)免费用于非商业用途(适用于Windows,Linux和Mac的版本)
  • 此解决方案使用Q的内核(内部命名为k4),因此我们需要具有k扩展名的脚本文件或k模式下的交互式解释器(第一个提示符下的\命令)。相比之下,该语言的“冗长”(清晰)版本需要带有q扩展名的脚本,并且是交互式解释器的默认模式。

测试

f ((1 1 1; 1 1 1; 0 1 1; 1 1 1; 1 1 1; 1 1 1; 1 1 1; 1 1 1)
   (1 1 1; 1 0 1; 1 1 1; 1 1 1; 1 1 1; 1 1 1; 1 1 1; 1 1 1)
   (1 1 1; 1 1 0; 1 1 1; 1 1 1; 1 1 1; 1 1 1; 1 1 1; 1 1 1)
   (1 1 1; 1 1 1; 1 1 0; 1 1 1; 1 1 1; 1 1 1; 1 1 1; 1 1 1)
   (1 1 1; 1 1 1; 1 1 1; 1 0 1; 1 1 1; 1 1 1; 1 1 1; 1 1 1)
   (1 1 1; 1 1 1; 1 1 1; 1 0 1; 1 1 1; 1 1 1; 1 1 1; 1 1 1)
   (1 1 1; 1 1 1; 1 1 1; 0 1 1; 1 1 1; 1 1 1; 1 1 1; 1 1 1))

##X#####
###\####
###|####
###|####
##/#####
#/######
#|######
##\#####

f ((41 27 38; 12 83 32; 50 53 35; 46 32 26; 55 89 82; 75 30 87;  2 11 64;  8 55 22)
   (56 21  0; 83 25 38; 43 75 63; 56 60 77; 68 55 89; 99 48 67; 94 30  9; 62 62 58)
   (23 18 40; 24 47 61; 96 45 72; 71  6 48; 75 63 98; 93 56 51; 23 31 30; 49 34 99)
   (20 47 42; 62 79 72; 32 28 44; 68 61 55; 62 39 57;  4 17 49; 97 85  6; 91 18 12)
   (51 50 11; 32 39 56; 12 82 23; 33 88 87; 60 55 22; 29 78 14; 70 11 42; 63 94 67)
   (75 64 60; 27 79 86; 70 72 56; 55 45 32; 95 67 12; 87 93 98; 81 36 53; 38 22 93)
   (31 80 50; 77 71 22; 59 46 86; 64 71 53; 41 19 95; 62 71 22; 92 80 41; 26 74 29))

######X#
#####/##
####/###
#####\##
######\#
######|#
######|#
#######\

说明

出于说明目的,我们假设进行第二次测试(矩阵((41 27 38; 12 83 32; ....

我们转换原始矩阵(在代码级别为m):我们为左,上和右位移定义矩阵,而不是为每个坐标使用三元组的原始矩阵。左矩阵包含7x7值(我们删除第一列),上矩阵包含7x8,右矩阵7x7(我们删除最后一列)。

left                           up                         right
12 50 46 55 75 2  8       27 83 53 32 89 30 11 55     38 32 35 26 82 87 64
83 43 56 68 99 94 62      21 25 75 60 55 48 30 62     0  38 63 77 89 67 9 
24 96 71 75 93 23 49      18 47 45 6  63 56 31 34     40 61 72 48 98 51 30
62 32 68 62 4  97 91      47 79 28 61 39 17 85 18     42 72 44 55 57 49 6 
32 12 33 60 29 70 63      50 39 82 88 55 78 11 94     11 56 23 87 22 14 42
27 70 55 95 87 81 38      64 79 72 45 67 93 36 22     60 86 56 32 12 98 53
77 59 64 41 62 92 26      80 71 46 71 19 71 80 74     50 22 86 53 95 22 41

为了计算最终头寸,我们需要评估最小成本路径。我们假设初始成本为0 0 0 0 0 0 0 0 0(到达第一行每一列的成本),并随下一行进行迭代。在第i列,我们计算三个值:

  • 前i + 1个值的成本加上left [i + 1]。我们删除成本的第一部分(要添加的班次和alineates列),然后将各个部分相加

  • 以前的i值的成本加[i]。我们将各个组成部分相加

  • 先前i-1值加上right [i-1]的成本。我们删除成本的最后一个部分(要添加的班次和alineates列),然后将各个部分相加

为了计算最小值,我们完成无穷大的左成本前置和无穷大的右成本追加:用8个分量的3个向量,计算最小分量与分量之间的差。结果值是新迭代的基本成本

对于第一次迭代,我们获得值(0W在Q中为无穷大)

0W 12 50 46 55 75 2  8
27 83 53 32 89 30 11 55
38 32 35 26 82 87 64 0W

并计算每列的最小值

27 12 35 26 55 30 2 8

在所有迭代之后,我们具有到达每个正方形的最低成本(假设第0行位于顶部,第7行位于底部)。我们仅对最后一栏感兴趣,但出于说明目的,我绘制了所有中间结果

0   0   0   0   0   0   0   0
27  12  35  26  55  30  2   8
27  37  78  82  110 78  11  70
45  61  123 88  173 129 34  104
87  123 151 143 212 133 40  122
98  155 163 176 234 147 51  185
158 182 219 208 246 234 87  207
208 204 265 261 265 256 128 233

现在,我们在最后一行(第6列的128)处找到了最小值。这就是路径的结尾(输出中的X字符)。

我们再次重复成本计算,但是现在我们从获得每个最小值的角度注释了方向(用于计算最小值的3个值中的其中一个是所选值)。

\|/|\///
\\\\\/|/
\\\|//|/
\\|\//|/
\\|//|\/
\\//|\|/
\|/|/|\/

我们反转行,在位置6处放置“ X”,并仅保留在列6处结束的路径(其他路径由#代替)

######X#
#####/##
####/###
#####\##
######\#
######|#
######|#
#######\

我从没听说过Q,但是感谢您这么详尽的答复:)
gilad hoch
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.