利用DeepSeek用预计算格点邻居的方法优化求解集合数学题程序

用“预先计算每个点能够和它在一个集合(即满足 (a-x)(b-y)≤0 的条件)的所有点作为邻居,每次在未选的邻居点中尝试,而不是所有未选的点中尝试”的思路改写程序,
结果他给出的程序更慢,让他修改,结果又恢复了原方法
于是更详细地描述算法:如果一个点有n个邻居,那么最好的情况就是这n+1个数构成的集合就是具有最大元素个数的集合,否则去掉一些点才能构成最大元素个数的集合,那么从第一个邻居开始,看余下的点是否是它的邻居,如果某点不是,则删除此点,如果删除后元素个数少于前面已有的最大个数,去掉该邻居,每次的搜索均不超过邻居的范围,编写程序,不做别的
得到的程序如下

def find_maximal_subsets_optimized(n):
    """
    使用邻居限制的搜索空间来找到所有满足条件的最大子集 B
    """
    all_points = [(i, j) for i in range(1, n + 1) for j in range(1, n + 1)]
    
    # 预计算每个点的邻居(可以共存于同一集合的点)
    neighbors = {}
    for point in all_points:
        neighbors[point] = []
    
    for i, point1 in enumerate(all_points):
        a, b = point1
        for j, point2 in enumerate(all_points):
            if i == j:
                continue
            x, y = point2
            if (a - x) * (b - y) <= 0:
                neighbors[point1].append(point2)
    
    max_size = 0
    maximal_subsets = []
    
    def backtrack(current_set, candidate_neighbors):
        nonlocal max_size
        
        current_size = len(current_set)
        if current_size > max_size:
            max_size = current_size
            maximal_subsets.clear()
            maximal_subsets.append(set(current_set))
        elif current_size == max_size:
            maximal_subsets.append(set(current_set))
        
        # 如果没有候选点了,返回
        if not candidate_neighbors:
            return
        
        # 如果当前集合大小加上剩余候选点数 <= 已知最大大小,剪枝
        if current_size + len(candidate_neighbors) < max_size:  #只有这一处需要修改,从<=改为<,以输出所有满足的集合
            return
        
        # 尝试每个候选点
        for i, point in enumerate(candidate_neighbors):
            # 检查该点是否与当前集合中所有点都满足条件
            can_add = True
            for existing_point in current_set:
                a, b = point
                x, y = existing_point
                if (a - x) * (b - y) > 0:
                    can_add = False
                    break
            
            if can_add:
                # 新的候选集是当前候选集中该点之后的点,且必须是该点的邻居
                new_candidates = []
                for candidate in candidate_neighbors[i+1:]:
                    if candidate in neighbors[point]:
                        new_candidates.append(candidate)
                
                current_set.append(point)
                backtrack(current_set, new_candidates)
                current_set.pop()
    
    # 从每个点开始搜索
    for start_point in all_points:
        # 初始候选集是起始点的所有邻居(按顺序排列)
        initial_candidates = [p for p in neighbors[start_point] if p > start_point]
        backtrack([start_point], initial_candidates)
    
    # 去重
    unique_subsets = []
    seen = set()
    for s in maximal_subsets:
        key = tuple(sorted(s))
        if key not in seen:
            seen.add(key)
            unique_subsets.append(s)
    
    return unique_subsets, max_size

def main():
    n = 6  # 可以修改这个参数
    print(f"I = {{1, 2, ..., {n}}}")
    print("使用邻居限制搜索空间算法寻找最大子集...")
    
    result, max_size = find_maximal_subsets_optimized(n)
    
    print(f"\n最大元素个数: {max_size}")
    print(f"去重前集合数: {len(maximal_subsets)}")
    print(f"找到 {len(result)} 个满足条件的最大集合 B:")
    
    for i, B in enumerate(result, 1):
        print(f"{i}: {sorted(B)}")

if __name__ == "__main__":
    main()

这个版本只输出了一个集合,只要修改一个符号,就能输出所有,见程序中注释。
性能比较

n=6
I = {1, 2, ..., 6}
使用优化算法寻找最大子集...


最大元素个数: 11
找到 252 个满足条件的最大集合 B:
real	0m0.060s
user	0m0.056s
sys	0m0.000s
原程序

real	0m0.298s
user	0m0.296s
sys	0m0.000s

n=7

I = {1, 2, ..., 7}
使用优化算法寻找最大子集...

最大元素个数: 13
找到 924 个满足条件的最大集合 B:
real	0m0.445s
user	0m0.444s
sys	0m0.000s
原程序
real	0m4.067s
user	0m4.064s
sys	0m0.000s
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值