1到2n这2n个数平均分成两份 abs(ai-bi)=k 求个数

探讨了将从1到2n的数均匀分为两组,使得每组排序后,相同位置的数差的绝对值至少为k的问题。通过递归和组合方法,对比两种解决方案的正确性和效率。

输入是两个正整数n和k,把从1到2n这2n个数平均分成两份(每份n个数),每份分别排序,排序完成后的数组假设叫a和b,要求abs(ai-bi)>=k, (相同位置的数差的绝对值不少于k),输出有多少种分法。


Backtrack is straighforward, welcome other better solutions:

from itertools import combinations

class Solution:
    def cal_ways(self, n, k):
        def dfs(toset, sta, y):
            nonlocal k,n
            l = len(sta)
            if (l == n and y == n):
                return 1
            elif (l == y and l+k <= n):
                return 2*dfs(k+toset, sta+[i+toset for i in range(k)], y)
            elif (l == y and l+k > n):
                return 0
            else:
                ret = 0
                if (l < n):
                    ret += dfs(toset+1, sta+[toset], y)
                if ((abs(sta[y]-toset) >= k)):
                    ret += dfs(toset+1, sta, y+1)
                return ret
        res = dfs(1+k, [i+1 for i in range(k)], 0)
        return res

    def cal_direct(self, n, k):
        total = [i+1 for i in range(n*2)]
        cnt,xycnt = 0,0

        for comb in combinations([i+1 for i in range(n*2)], n):
            a = list(comb)
            b = sorted(list(set(total).difference(set(a))))

            if (all(abs(a[i]-b[i]) >= k for i in range(n))):
                cnt += 1
        return cnt >> 1

s = Solution()


for i in range(1,10):
    for j in range(1,i+1):
        res1 = s.cal_ways(i, j)
        res2 = s.cal_direct(i, j)
        if (res1 != res2):
            print("n={0} k={1} res1={2} res2={3}".format(i,j,res1,res2))
print("Finished!!!")

Dependencies are the major difficulty. E.g., n=7, k=3, after arrangement of [1,2,3],the arrangement of 4,5,6 has 3 scenarios:

a=[1, 2, 3, 4, 7, 8, 9] b=[5, 6, 10, 11, 12, 13, 14]
a=[1, 2, 3, 4, 7, 8, 10] b=[5, 6, 9, 11, 12, 13, 14]
a=[1, 2, 3, 4, 7, 8, 11] b=[5, 6, 9, 10, 12, 13, 14]
a=[1, 2, 3, 4, 7, 9, 10] b=[5, 6, 8, 11, 12, 13, 14]
a=[1, 2, 3, 4, 7, 9, 11] b=[5, 6, 8, 10, 12, 13, 14]
a=[1, 2, 3, 4, 7, 10, 11] b=[5, 6, 8, 9, 12, 13, 14]
a=[1, 2, 3, 4, 8, 9, 10] b=[5, 6, 7, 11, 12, 13, 14]
a=[1, 2, 3, 4, 8, 9, 11] b=[5, 6, 7, 10, 12, 13, 14]
a=[1, 2, 3, 4, 8, 10, 11] b=[5, 6, 7, 9, 12, 13, 14]
a=[1, 2, 3, 4, 9, 10, 11] b=[5, 6, 7, 8, 12, 13, 14]
a=[1, 2, 3, 4, 12, 13, 14] b=[5, 6, 7, 8, 9, 10, 11]

a=[1, 2, 3, 5, 7, 8, 9] b=[4, 6, 10, 11, 12, 13, 14]
a=[1, 2, 3, 5, 7, 8, 10] b=[4, 6, 9, 11, 12, 13, 14]
a=[1, 2, 3, 5, 7, 8, 11] b=[4, 6, 9, 10, 12, 13, 14]
a=[1, 2, 3, 5, 7, 9, 10] b=[4, 6, 8, 11, 12, 13, 14]
a=[1, 2, 3, 5, 7, 9, 11] b=[4, 6, 8, 10, 12, 13, 14]
a=[1, 2, 3, 5, 7, 10, 11] b=[4, 6, 8, 9, 12, 13, 14]
a=[1, 2, 3, 5, 8, 9, 10] b=[4, 6, 7, 11, 12, 13, 14]
a=[1, 2, 3, 5, 8, 9, 11] b=[4, 6, 7, 10, 12, 13, 14]
a=[1, 2, 3, 5, 8, 10, 11] b=[4, 6, 7, 9, 12, 13, 14]
a=[1, 2, 3, 5, 9, 10, 11] b=[4, 6, 7, 8, 12, 13, 14]
a=[1, 2, 3, 5, 12, 13, 14] b=[4, 6, 7, 8, 9, 10, 11]

a=[1, 2, 3, 6, 7, 8, 9] b=[4, 5, 10, 11, 12, 13, 14]
a=[1, 2, 3, 6, 7, 8, 10] b=[4, 5, 9, 11, 12, 13, 14]
a=[1, 2, 3, 6, 7, 8, 11] b=[4, 5, 9, 10, 12, 13, 14]
a=[1, 2, 3, 6, 7, 9, 10] b=[4, 5, 8, 11, 12, 13, 14]
a=[1, 2, 3, 6, 7, 9, 11] b=[4, 5, 8, 10, 12, 13, 14]
a=[1, 2, 3, 6, 7, 10, 11] b=[4, 5, 8, 9, 12, 13, 14]
a=[1, 2, 3, 6, 8, 9, 10] b=[4, 5, 7, 11, 12, 13, 14]
a=[1, 2, 3, 6, 8, 9, 11] b=[4, 5, 7, 10, 12, 13, 14]
a=[1, 2, 3, 6, 8, 10, 11] b=[4, 5, 7, 9, 12, 13, 14]
08-20
【Koopman】遍历论、动态模态分解和库普曼算子谱特性的计算研究(Matlab代码实现)内容概要:本文围绕【Koopman】遍历论、动态模态分解和库普曼算子谱特性的计算研究展开,重点介绍基于Matlab的代码实现方法。文章系统阐述了遍历理论的基本概念、动态模态分解(DMD)的数学原理及其与库普曼算子谱特性之间的内在联系,展示了如何通过数值计算手段分析非线性动力系统的演化行为。文中提供了完整的Matlab代码示例,涵盖数据驱动的模态分解、谱分析及可视化过程,帮助读者理解并复现相关算法。同时,文档还列举了多个相关的科研方向和技术应用场景,体现出该方法在复杂系统建模与分析中的广泛适用性。; 适合人群:具备一定动力系统、线性代数与数值分析基础,熟悉Matlab编程,从事控制理论、流体力学、信号处理或数据驱动建模等领域研究的研究生、博士生及科研人员。; 使用场景及目标:①深入理解库普曼算子理论及其在非线性系统分析中的应用;②掌握动态模态分解(DMD)算法的实现与优化;③应用于流体动力学、气候建模、生物系统、电力系统等领域的时空模态提取与预测;④支撑高水平论文复现与科研项目开发。; 阅读建议:建议读者结合Matlab代码逐段调试运行,对照理论推导加深理解;推荐参考文中提及的相关研究方向拓展应用场景;鼓励在实际数据上验证算法性能,并尝试改进与扩展算法功能。
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值