分治算法实例

实验目的

1. 了解分治策略算法思想及基本原理;

2. 掌握使用分治算法求解问题的一般特征;

3. 掌握分解、治理的方法;

4. 能够针对实际问题,能够正确的分解、治理,设计分治算法;

5. 能够正确分析算法的时间复杂度和空间复杂度。

二、实验任务

下列2个问题中任选一个完成

1、棋盘覆盖问题:给定一个2k×2k的棋盘(具体图例见教材),有一个特殊棋格,拥有一个特殊棋格的棋盘称为特殊棋盘。现要用四种L型骨牌(具体图例见教材)覆盖特殊棋盘上除特殊棋格外的全部棋格,不能重叠,找出覆盖方案。

2、邮局选址问题:对一个以XY轴表达的城市里,n个居民点散乱分布,居民点位置可以用坐标(x,y)表示,任意两点(x1,y1)(x2,y2)间距离可以用| x1-x1|+|y1-y2|度量,居民希望在城市中选择建立邮局的最佳位置,使得n个居民点到邮局的距离综合最小

三、审题结果

学生撰写内容

四、问题建模结果

给定n 个居民点的位置,编程计算n 个居民点到邮局的距离总和的最小值。

输入由多组测试数据组成。

每组测试数据输入的第1 行是居民点数n,1≤n≤10000。接下来n 行是居民点的位置,每行2 个整数x 和y,-10000≤x,y≤10000。

因为街区中任意2 点(x1,y1)和(x2,y2)之间的距离可以用数值 |x1-x2 |+ |y1-y2 |度量;

那么:

邮局的x坐标只与n个居民点的x坐标相关;

邮局的y 坐标只与n个居民点的y坐标相关;

以求x坐标为例

假设对n个居民点的x坐标按大小排序后为x1,x2......xn;

对x1,xn两点来说,最近的点肯定在x1,xn之间,且跟两点的距离和==xn-x1;

对x2,x(n-1)两点来说,最近的点肯定在x2,x(n-1)之间,且跟两点的距离和==x(n-1)-x2;

....

所以若n为奇数,则邮局的x坐标取最中间的值时最小;

所以若n为偶数,则邮局的x坐标可以取最中间两个值的之间的任意值;

最终公式:x=(x(n/2+1)+x(n/2+2)+...+xn)-(x1+x2+..+x(n/2))

 

五、算法实现部分

覆盖问题


# 开发时间:2024-03-20 14:01
def chessBoard(tr, tc, dr, dc, size):
    if size == 1:
        return
    global tile
    global board
    tile += 1
    t = tile
    s = size // 2
    if dr < tr + s and dc < tc + s:
        chessBoard(tr, tc, dr, dc, s)
    else:
        board[tr + s - 1][tc + s - 1] = t
        chessBoard(tr, tc, tr + s - 1, tc + s - 1, s)
    if dr < tr + s and dc >= tc + s:
        chessBoard(tr, tc + s, dr, dc, s)
    else:
        board[tr + s - 1][tc + s] = t
        chessBoard(tr, tc + s, tr + s - 1, tc + s, s)
    if dr >= tr + s and dc < tc + s:

        chessBoard(tr + s, tc, dr, dc, s)
    else:

        board[tr + s][tc + s - 1] = t

        chessBoard(tr + s, tc, tr + s, tc + s - 1, s)

    if dr >= tr + s and dc >= tc + s:

        chessBoard(tr + s, tc + s, dr, dc, s)
    else:

        board[tr + s][tc + s] = t

        chessBoard(tr + s, tc + s, tr + s, tc + s, s)


def show_chess(board):
    n = len(board)
    for i in range(n):
        for j in range(n):
            print(board[i][j], end=" ")
        print('')


tile = 0

size = int(input())
n = pow(2, size)
if __name__ == '__main__':
    dr, dc = map(int, input().split())
board = [[0 for x in range(n)] for y in range(n)]
board[dr - 1][dc - 1] = -1
chessBoard(0, 0, dr - 1, dc - 1, n)
show_chess(board)

2、邮局选址问题:

n = int(input())
lx = []
ly = []
for i in range(n):
    x, y = map(int, input().split())
    lx.append(x)
    ly.append(y)
lx = sorted(lx)  # 排序
ly = sorted(ly)
if n % 2 != 0:  # 奇数,求中位数
    z = int((n - 1) / 2)
    x0 = lx[z]
    y0 = ly[z]
else:  # 偶数
    z = int(n / 2)
    x0 = int((lx[z] + lx[z - 1]) / 2)
    y0 = int((ly[z] + ly[z - 1]) / 2)  # 题目要int
sumx = 0
sumy = 0
for j in lx:
    p = abs(x0 - j)
    sumx = sumx + p
for k in ly:
    q = abs(y0 - k)
    sumy = sumy + q
print(sumx + sumy)

六、实验结果分析

学生撰写内容

七、实验总结

学生撰写内容

  • 4
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值