算法-给你一个小于50的数字 a ,请写出一个算法得到所有可能的数字集合,每个数字集合满足以下条件:

发布于 2016-10-13 03:47:23 字数 421 浏览 1268 评论 1

给你一个小于50的数字 a ,请写出一个算法得到所有可能的数字集合,每个数字集合满足以下条件:

  1. 集合中所有数字的和等于a;

  2. 集合中的所有数字均大于1;

  3. 集合中可以出现重复数字;

例如:

2 -> {2},
3->{3},
4->{[4], [2, 2]},
5->{[5], [3, 2]},
6->{[6], [4, 2], [3, 3], [2, 2, 2]}
7->{[7], [5, 2], [4, 3], [3, 2, 2]}
8->{[8], [6, 2], [5, 3], [4, 4], [4, 2, 2], [3, 3, 2], [2, 2, 2, 2]}

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

晚风撩人 2017-09-03 07:24:04

Haskell:

solve n = go [(n,[])] []
where
go [] result = result
go ((left, path):xs) result
| left == 1 = go xs result
| left == 0 = go xs (path:result)
| otherwise = go (next (left, path) ++ xs) result

next (left, path) = map (l -> (left - l, l:path))
$ filter (lessThanHead path) [2..left]

lessThanHead [] x = True
lessThanHead (y:ys) x = x <= y

-- Test --

ghci> mapM_ (print . solve) [2..8]
[[2]]
[[3]]
[[4],[2,2]]
[[5],[2,3]]
[[6],[2,4],[3,3],[2,2,2]]
[[7],[2,5],[3,4],[2,2,3]]
[[8],[2,6],[3,5],[4,4],[2,2,4],[2,3,3],[2,2,2,2]]

50时有30701种组合。

趣味:用SMT求解器求解

{-# LANGUAGE ScopedTypeVariables #-}
import Data.SBV.Bridge.Z3
import Control.Monad (foldM_, mapM_)

-- 把一个数值m分成n份,且满足题目条件
equalsMN m n = do
-- 新建n个变量(s0, s1 .. sn-1)
vars :: [SInt16] <- mkExistVars n
-- 每个变量s满足 2 <= s <= m
mapM_ (x -> constrain (x .>= 2 &&& x .<= (fromIntegral m))) vars
-- 变量满足 s0 <= s1 <= ... <= sn-1,保证结果不重复
foldM_ (x y -> constrain (x .<= y) >> return y) 0 vars
-- 全部变量的和等于m
return $ sum vars .== (fromIntegral (m::Int))

-- 依次求出把m分成 1 ... m/2 份时的解
solveM m = mapM (allSat . equalsMN m) [1 .. m `div` 2]

求解9的时候是这样的:

[Solution #1:
s0 = 9 :: SInt16
This is the only solution.,Solution #1:
s0 = 4 :: SInt16
s1 = 5 :: SInt16
Solution #2:
s0 = 2 :: SInt16
s1 = 7 :: SInt16
Solution #3:
s0 = 3 :: SInt16
s1 = 6 :: SInt16
Found 3 different solutions.,Solution #1:
s0 = 2 :: SInt16
s1 = 3 :: SInt16
s2 = 4 :: SInt16
Solution #2:
s0 = 2 :: SInt16
s1 = 2 :: SInt16
s2 = 5 :: SInt16
Solution #3:
s0 = 3 :: SInt16
s1 = 3 :: SInt16
s2 = 3 :: SInt16
Found 3 different solutions.,Solution #1:
s0 = 2 :: SInt16
s1 = 2 :: SInt16
s2 = 2 :: SInt16
s3 = 3 :: SInt16
This is the only solution.]

这个方法要比第一个解法慢很多,不过更加“声明式”。

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文