haskell 基础题解(53)

车队入栈问题

【题目】编号为 1,2…n 的一个车队,从右向左行驶。道路只能容一辆车通过,无法超车。
中间有个死胡同,作为检查站。所有经过车辆必需入站检查。也可能进行很复杂检查,也可能不检查,入站后,马上出站继续上左边的路行驶。检查站容量很大,且也是单车道。
求这n辆车最后在左边道路上的排列有多少种可能。在这里插入图片描述
很显然,检查站就是一个栈结构,只能在其顶端操作。要么右边的一辆车进入,要么最靠外边的一辆车开出去上左边的路上。

那是不是可以形成的任意的顺序呢?显然不可能。比如说,最后的一辆车要排在左边第一的位置。那么,它前边的所有车必须都是栈中。而进入了栈中后,出来的顺序就已经固定了。

看似杂的问题,用递归来思考就会有点眉目了。。。。

carque :: Int -> Integer
carque n = f n 0
    where
        f 0 _ = 1
        f x 0 = f (x-1) 1
        f x y = f (x-1) (y+1) + f x (y-1)

main :: IO ()
main = do
    let a = [1..10]
        b = map carque a
        c = map show $ zip a b 
    putStrLn $ unlines c

算法关键是 f 的两个参数。第一个表示右边的车辆数。第二个表示栈中车辆数。

如果问的不是有多少种情况,而是列出所有情况,该如何呢?

此时可以这样思考:
第1辆车在最后的队列中会在什么位置呢?
可以在第1,第2,第3,。。。。一直到最尾位置。
假设它在第 m 位,则前有 m-1 辆, 后有 n-m 辆
显然,产生这样局面的过程是这样的:
它先在栈底睡大觉,等m-1辆车各种折腾,最后都出去了,它才出去,然后是它后面的n-m辆继续折腾。
这样,就对原问题,分治为两个相似的问题了。

import Data.List (inits, tails)

carque :: [a] -> [[a]]
carque [] = [[]]
carque (x:xs) = concat $ zipWith f ps qs
    where 
        ps = map carque (inits xs)
        qs = map carque (tails xs)
        f p1 p2 = [ i1 ++ [x] ++ i2 | i1<-p1, i2<-p2] 

main :: IO ()
main = print $ carque "abc"
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值