- iOS/Objective-C 元类和类别
- objective-c - -1001 错误,当 NSURLSession 通过 httpproxy 和/etc/hosts
- java - 使用网络类获取 url 地址
- ios - 推送通知中不播放声音
这将是一篇很长的文章,只是为了好玩,所以如果你没有太多时间最好去帮助人们解决更重要的问题:)
xbox 上最近发布了一款名为“Tower Bloxx”的游戏。游戏的一部分是以最佳方式在 field 上放置不同颜色的塔,以最大限度地增加最有值(value)的塔的数量。我写了一个算法来确定最有效的塔放置,但它不是很有效,而且几乎只是强制所有可能的组合。对于具有 4 种塔类型的 4x4 field ,它在大约 1 小时内解决它,5 种塔类型将花费大约 40 小时,这太多了。
规则如下:有 5 种类型的塔可以放置在 field 上。有几种类型的字段,最简单的就是 4x4 矩阵,其他字段有一些您无法构建的“空白”。您的目标是在一 block field 上放置尽可能多的最有值(value)的塔,以最大化一 block field 上的总塔值(value)(假设所有塔都是一次 build 的,没有轮流)。
塔类型(按值(value)从低到高的顺序):
这意味着例如绿塔在北、南、西或东相邻单元格中应至少有 1 个红色和 1 个蓝色塔(对角线不算)。白色塔应该被所有其他颜色包围。
这是我在 4x4 field 上的 4 座塔的算法:
我想出的唯一优化是跳过不包含任何最有值(value)的塔的组合。它跳过了一些处理,但我仍然遍历所有 4^16 组合。
想过如何改进吗?如果使用 java 或 php,代码示例会很有帮助。
--------更新--------
添加更多非法状态后(黄色不能建在角落里,白色不能建在角落和边缘上, field 应该至少包含每种类型的塔),意识到只能 build 1 座白色塔在 4x4 领域和优化 java 代码上,总时间从 40 小时减少到 ~16 小时。也许线程会将其缩短到 10 小时,但这可能是暴力破解的极限。
最佳答案
我发现这个问题很有趣,而且由于我正在自学 Haskell,所以我决定尝试用该语言实现解决方案。
我想过分支定界,但想不出一个好的方法来绑定(bind)解决方案,所以我只是通过丢弃违反规则的板来进行一些修剪。
我的算法从一个“空”板开始工作。它将每种可能的塔颜色放在第一个空槽中,然后在每种情况下(每种颜色)递归调用自身。递归调用尝试第二个槽中的每种颜色,再次递归,直到棋盘已满。
在放置每个塔时,我会检查刚刚放置的塔及其所有相邻塔,以验证它们是否遵守规则,将任何空的相邻塔视为通配符。所以如果一个白塔有四个空的邻居,我认为它是有效的。如果某个位置无效,我不会对该位置进行递归,有效地修剪其下的整个可能性树。
按照代码的编写方式,我会生成一个包含所有可能解决方案的列表,然后查看该列表以找到最佳解决方案。实际上,由于 Haskell 的惰性计算,列表元素是在搜索功能需要它们时生成的,并且由于它们再也不会被引用,它们可以立即用于垃圾回收,所以即使是 5x5 的板,内存使用量也相当小(2 MB)。
性能还不错。在我的 2.1 GHz 笔记本电脑上,程序的编译版本使用一个内核在大约 50 秒内解决了 4x4 的情况。我现在正在运行一个 5x5 示例,看看需要多长时间。由于函数式代码很容易并行化,我也将尝试并行处理。有一个并行化的 Haskell 编译器,它不仅可以将工作分散到多个内核上,还可以分散到多台机器上,这是一个非常可并行化的问题。
到目前为止,这是我的代码。我意识到您指定了 Java 或 PHP,而 Haskell 则完全不同。如果你想玩它,你可以修改底部上方变量“bnd”的定义来设置棋盘大小。只需将其设置为 ((1,1),(x, y)),其中 x 和 y 分别是列数和行数。
import Array
import Data.List
-- Enumeration of Tower types. "Empty" isn't really a tower color,
-- but it allows boards to have empty cells
data Tower = Empty | Blue | Red | Green | Yellow | White
deriving(Eq, Ord, Enum, Show)
type Location = (Int, Int)
type Board = Array Location Tower
-- towerScore omputes the score of a single tower
towerScore :: Tower -> Int
towerScore White = 100
towerScore t = (fromEnum t) * 10
-- towerUpper computes the upper bound for a single tower
towerUpper :: Tower -> Int
towerUpper Empty = 100
towerUpper t = towerScore t
-- boardScore computes the score of a board
boardScore :: Board -> Int
boardScore b = sum [ towerScore (b!loc) | loc <- range (bounds b) ]
-- boardUpper computes the upper bound of the score of a board
boardUpper :: Board -> Int
boardUpper b = sum [ bestScore loc | loc <- range (bounds b) ]
where
bestScore l | tower == Empty =
towerScore (head [ t | t <- colors, canPlace b l t ])
| otherwise = towerScore tower
where
tower = b!l
colors = reverse (enumFromTo Empty White)
-- Compute the neighbor locations of the specified location
neighborLoc :: ((Int,Int),(Int,Int)) -> (Int,Int) -> [(Int,Int)]
neighborLoc bounds (col, row) = filter valid neighborLoc'
where
valid loc = inRange bounds loc
neighborLoc' = [(col-1,row),(col+1,row),(col,row-1),(col,row+1)]
-- Array to store all of the neighbors of each location, so we don't
-- have to recalculate them repeatedly.
neighborArr = array bnd [(loc, neighborLoc bnd loc) | loc <- range bnd]
-- Get the contents of neighboring cells
neighborTowers :: Board -> Location -> [Tower]
neighborTowers board loc = [ board!l | l <- (neighborArr!loc) ]
-- The tower placement rule. Yields a list of tower colors that must
-- be adjacent to a tower of the specified color.
requiredTowers :: Tower -> [Tower]
requiredTowers Empty = []
requiredTowers Blue = []
requiredTowers Red = [Blue]
requiredTowers Green = [Red, Blue]
requiredTowers Yellow = [Green, Red, Blue]
requiredTowers White = [Yellow, Green, Red, Blue]
-- cellValid determines if a cell satisfies the rule.
cellValid :: Board -> Location -> Bool
cellValid board loc = null required ||
null needed ||
(length needed <= length empties)
where
neighbors = neighborTowers board loc
required = requiredTowers (board!loc)
needed = required \\ neighbors
empties = filter (==Empty) neighbors
-- canPlace determines if 'tower' can be placed in 'cell' without
-- violating the rule.
canPlace :: Board -> Location -> Tower -> Bool
canPlace board loc tower =
let b' = board // [(loc,tower)]
in cellValid b' loc && and [ cellValid b' l | l <- neighborArr!loc ]
-- Generate a board full of empty cells
cleanBoard :: Array Location Tower
cleanBoard = listArray bnd (replicate 80 Empty)
-- The heart of the algorithm, this function takes a partial board
-- (and a list of empty locations, just to avoid having to search for
-- them) and a score and returns the best board obtainable by filling
-- in the partial board
solutions :: Board -> [Location] -> Int -> Board
solutions b empties best | null empties = b
solutions b empties best =
fst (foldl' f (cleanBoard, best) [ b // [(l,t)] | t <- colors, canPlace b l t ])
where
f :: (Board, Int) -> Board -> (Board, Int)
f (b1, best) b2 | boardUpper b2 <= best = (b1, best)
| otherwise = if newScore > lstScore
then (new, max newScore best)
else (b1, best)
where
lstScore = boardScore b1
new = solutions b2 e' best
newScore = boardScore new
l = head empties
e' = tail empties
colors = reverse (enumFromTo Blue White)
-- showBoard converts a board to a printable string representation
showBoard :: Board -> String
showBoard board = unlines [ printRow row | row <- [minrow..maxrow] ]
where
((mincol, minrow), (maxcol, maxrow)) = bounds board
printRow row = unwords [ printCell col row | col <- [mincol..maxcol] ]
printCell col row = take 1 (show (board!(col,row)))
-- Set 'bnd' to the size of the desired board.
bnd = ((1,1),(4,4))
-- Main function generates the solutions, finds the best and prints
-- it out, along with its score
main = do putStrLn (showBoard best); putStrLn (show (boardScore best))
where
s = solutions cleanBoard (range (bounds cleanBoard)) 0
best = s
此外,请记住这是我的第一个重要的 Haskell 程序。我相信它可以做得更优雅、更简洁。
更新:由于做一个5x5的5色还是很费时间的(我等了12个小时还没做完),我又看了看如何使用bounding to修剪更多的搜索树。
我的第一种方法是通过假设每个空单元格都填充有白色塔来估计部分填充板的上限。然后我修改了“解决方案”函数以跟踪看到的最佳分数并忽略任何上限小于该最佳分数的棋盘。
这对一些人有所帮助,将 4x4x5 板从 23 秒减少到 15 秒。为了进一步改进它,我修改了上限函数以假设每个 Empty 都填充了可能的最佳塔,与现有的非空单元格内容一致。这有很大帮助,将 4x4x5 时间减少到 2 秒。
在 5x5x5 上运行它花费了 2600 秒,给出了以下板:
G B G R B
R B W Y G
Y G R B R
B W Y G Y
G R B R B
得分为 730。
我可能会进行另一次修改,让它找到所有的最高得分板,而不仅仅是一个。
关于algorithm - 尝试构建算法以在游戏中放置最佳塔,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/1626189/
我在一本书(Interview Question)中读到这个问题,想在这里详细讨论这个问题。请点亮它。 问题如下:- 隐私和匿名化 马萨诸塞州集团保险委员会早在 1990 年代中期就有一个绝妙的主意
我最近接受了一次面试,面试官给了我一些伪代码并提出了相关问题。不幸的是,由于准备不足,我无法回答他的问题。由于时间关系,我无法向他请教该问题的解决方案。如果有人可以指导我并帮助我理解问题,以便我可以改
这是我的代码 public int getDist(Node root, int value) { if (root == null && value !=0) return
就效率而言,Strassen 算法应该停止递归并应用乘法的最佳交叉点是多少? 我知道这与具体的实现和硬件密切相关,但对于一般情况应该有某种指南或某人的一些实验结果。 在网上搜索了一下,问了一些他们认为
我想学习一些关于分布式算法的知识,所以我正在寻找任何书籍推荐。我对理论书籍更感兴趣,因为实现只是个人喜好问题(我可能会使用 erlang(或 c#))。但另一方面,我不想对算法进行原始的数学分析。只是
我想知道你们中有多少人实现了计算机科学的“ classical algorithms ”,例如 Dijkstra's algorithm或现实世界中的数据结构(例如二叉搜索树),而不是学术项目? 当有
我正在解决旧编程竞赛中的一些示例问题。在这个问题中,我们得到了我们有多少调酒师以及他们知道哪些食谱的信息。制作每杯鸡尾酒需要 1 分钟,我们需要使用所有调酒师计算是否可以在 5 分钟内完成订单。 解决
关闭。这个问题是opinion-based .它目前不接受答案。 想要改进这个问题? 更新问题,以便 editing this post 可以用事实和引用来回答它. 关闭 8 年前。 Improve
我开始学习 Nodejs,但我被困在中间的某个地方。我从 npm 安装了一个新库,它是 express -jwt ,它在运行后显示某种错误。附上代码和错误日志,请帮助我! const jwt = re
我有一个证书,其中签名算法显示“sha256rsa”,但指纹算法显示“sha1”。我的证书 SHA1/SHA2 的标识是什么? 谢谢! 最佳答案 TL;TR:签名和指纹是完全不同的东西。对于证书的强度
我目前在我的大学学习数据结构类(class),并且在之前的类(class)中做过一些算法分析,但这是我在之前的类(class)中遇到的最困难的部分。我们现在将在我的数据结构类(class)中学习算法分
有一个由 N 个 1x1 方格组成的区域,并且该区域的所有部分都是相连的(没有任何方格无法到达的方格)。 下面是一些面积的例子。 我想在这个区域中选择一些方块,并且两个相邻的方块不能一起选择(对角接触
我有一些多边形形状的点列表,我想将其包含在我页面上的 Google map 中。 我已经从原始数据中删除了尽可能多的不必要的多边形,现在我剩下大约 12 个,但它们非常详细以至于导致了问题。现在我的文
我目前正在实现 Marching Squares用于计算等高线曲线,我对此处提到的位移位的使用有疑问 Compose the 4 bits at the corners of the cell to
我正在尝试针对给定算法的约束满足问题实现此递归回溯函数: function BACKTRACKING-SEARCH(csp) returns solution/failure return R
是否有包含反函数的库? 作为项目的一部分,我目前正在研究测向算法。我正在使用巴特利特相关性。在 Bartlett 相关性中,我需要将已经是 3 次矩阵乘法(包括 Hermitian 转置)的分子除以作
关闭。这个问题不符合Stack Overflow guidelines .它目前不接受答案。 这个问题似乎与 help center 中定义的范围内的编程无关。 . 关闭 8 年前。 Improve
问题的链接是UVA - 1394 : And There Was One . 朴素的算法是扫描整个数组并在每次迭代中标记第 k 个元素并在最后停止:这需要 O(n^2) 时间。 我搜索了一种替代算法并
COM 中创建 GUID 的函数 (CoCreateGUID) 使用“分散唯一性算法”,但我的问题是,它是什么? 谁能解释一下? 最佳答案 一种生成 ID 的方法,该 ID 具有一定的唯一性保证,而不
在做一个项目时我遇到了这个问题,我将在这个问题的实际领域之外重新措辞(我想我可以谈论烟花的口径和形状,但这会使理解更加复杂).我正在寻找一种(可能是近似的)算法来解决它。 我有 n 个不同大小的容器,
我是一名优秀的程序员,十分优秀!