当前位置: 首页 > article >正文

解决leetcode第3426题所有安放棋子方案的曼哈顿距离

3426.所有安放棋子方案的曼哈顿距离

难度:困难

问题描述:

给你三个整数m,n和k。

给你一个大小为mxn的矩形格子,它包含k个没有差别的棋子。请你返回所有放置棋子的合法方案中,每对棋子之间的曼哈顿距离之和。

一个合法方案指的是将所有k个棋子都放在格子中且一个格子里至多只有一个棋子。

由于答案可能很大,请你将它对109+7取余后返回。

两个格子(xi,yi)和(xj,yj)的曼哈顿距离定义为|xi-xj|+|yi-yj|。

示例1:

输入:m=2,n=2,k=2

输出:8

解释:

放置棋子的合法方案包括:

前4个方案中,两个棋子的曼哈顿距离都为1。

后2个方案中,两个棋子的曼哈顿距离都为2。

所以所有方案的总曼哈顿距离之和为1+1+1+1+2+2=8。

示例2:

输入:m=1,n=4,k=3

输出:20

解释:

放置棋子的合法方案包括:

第一个和最后一个方案的曼哈顿距离分别为1+1+2=4。

中间两种方案的曼哈顿距离分别为1+2+3=6。

所以所有方案的总曼哈顿距离之和为4+6+6+4=20。

提示:

1<=m,n<=105

2<=m*n<=105

2<=k<=m*n

问题分析:

这个问题的难度系数比较高,leetcode的问题得分在6分以上即为困难,而完成这个题可以得8分。

追求本心,自然处理,符合人们解决问题的思考逻辑,这个题也是这样来考虑的,而且也确实解决了问题。

首先要解决的是,在一个mXn矩阵中的所有位置放置k个棋子,共有多少种不同的放置法,这又是一个排列组合问题。函数get_all(n,k)解决了这个问题,其的n表示矩阵中的n个位置,k表示放置k个棋子,用字符1表示有棋子,0表示没有棋子,通过递归处理将不同的放置方案求出,返回不同排列的放置方案列表。

其次是将这些不同排列放置方案中的一个进行解析,将放置了棋子的位置转换为mXn矩阵中的坐标并形成坐标列表返回,没有放置棋子的则不予处理。函数get_one_point_grid(m,n,c)解决了这个问题,其中m、n表示矩阵有m行n列,c为上一步求出的放置方案列表中的一个方案。

第三步则将所有的放置方案列表中的方案转化成坐标列表的形式并返回,函数get_all_grid(m,n,k)实现了这一要求,返回的列表中的每一个元素还是一个列表,对应一种放置方案解析出的放置了棋子的坐标序列。

此外还有如何计算两个坐标的曼哈顿值,函数get_distance(point1,point2)解决了这一问题。

计算一种放置方案的曼哈顿值之和用函数get_one_mhd(point_arr)解决。

最后是计算所有放置方案的曼哈顿值之和,函数get_all_mhd(b)解决了这个问题。其返回值即是这个问题的求解。

程序如下:

#将一个字符0插入到k个元素中形成的全排列
def get_in(ak):
    n=len(ak)
    e = []
    for i in range(n+1):
        b='0'
        a=ak[0:i]
        c=ak[i:]
        d=a+b+c
        e.append(d)
    return e

#生成n个位置有k个棋子的各种排列,其中n=行X列,用1表示放置了棋子,0表示未放置棋子
def get_all(n,k):
    if n==k:
        return ['1'*k]
    elif n==k+1:
        return get_in('1'*k)
    else:
        c=[]
        for i in get_all(n-1,k):
            c.extend(get_in(i))
        return list(set(c))

#将放置方案列表中的一个方案解析为mXn矩阵中的坐标,并返回坐标列表
def get_one_point_grid(m,n,c):
    a=[]
    count=0
    for i in range(m): #i表示行数
        for j in range(n): #j表示列数
            #如果字符串中该字符为1,提取该位置坐标,并加入到a列表中
            if c[count]=='1':
                a.append([i,j])
            count=count+1
    return a

#将放置方案列表中的所有方案解析为矩阵坐标列表并以更大的列表返回
def get_all_gird(m,n,k):
    a = get_all(m * n, k)
    print('以字符形式形成的方案:',a)
    b = []
    for i in a:
        b.append(get_one_point_grid(m, n, i))
    print('字符串方案转换为坐标列表方案:',b)
    return b

#计算两个格子的曼哈顿距离
def get_distance(point1,point2):
    x1=point1[0]
    y1=point1[1]
    x2=point2[0]
    y2=point2[1]
    return abs(x1-x2)+abs(y1-y2)

#计算以坐标列表形成的方案列表中的一种方案的曙哈顿距离之和
def get_one_mhd(point_arr):
    s=0
    n=len(point_arr)
    for i in range(n-1):
        for j in range(i+1,n):
            point1=point_arr[i]
            point2=point_arr[j]
            s=s+get_distance(point1,point2)
    print(f'正在处理坐标方案{point_arr},曼哈顿距离之和为{s}')
    return s

#计算所有坐标列表方案的曼哈顿距离之知
def get_all_mhd(b):
    s=0
    for i in b:
        s=s+get_one_mhd(i)
    return s

#主程序
m,n,k=eval(input('pls input m,n,k='))
b=(get_all_gird(m,n,k))
print('所有方案的总曼哈顿距离之和为:',get_all_mhd(b))

运行实例一

pls input m,n,k=1,4,3

以字符形式形成的方案: ['0111', '1011', '1101', '1110']

字符串方案转换为坐标列表方案: [[[0, 1], [0, 2], [0, 3]], [[0, 0], [0, 2], [0, 3]], [[0, 0], [0, 1], [0, 3]], [[0, 0], [0, 1], [0, 2]]]

正在处理坐标方案[[0, 1], [0, 2], [0, 3]],曼哈顿距离之和为4

正在处理坐标方案[[0, 0], [0, 2], [0, 3]],曼哈顿距离之和为6

正在处理坐标方案[[0, 0], [0, 1], [0, 3]],曼哈顿距离之和为6

正在处理坐标方案[[0, 0], [0, 1], [0, 2]],曼哈顿距离之和为4

所有方案的总曼哈顿距离之和为: 20

运行实例二

pls input m,n,k=2,2,2

以字符形式形成的方案: ['0101', '1010', '0110', '1001', '1100', '0011']

字符串方案转换为坐标列表方案: [[[0, 1], [1, 1]], [[0, 0], [1, 0]], [[0, 1], [1, 0]], [[0, 0], [1, 1]], [[0, 0], [0, 1]], [[1, 0], [1, 1]]]

正在处理坐标方案[[0, 1], [1, 1]],曼哈顿距离之和为1

正在处理坐标方案[[0, 0], [1, 0]],曼哈顿距离之和为1

正在处理坐标方案[[0, 1], [1, 0]],曼哈顿距离之和为2

正在处理坐标方案[[0, 0], [1, 1]],曼哈顿距离之和为2

正在处理坐标方案[[0, 0], [0, 1]],曼哈顿距离之和为1

正在处理坐标方案[[1, 0], [1, 1]],曼哈顿距离之和为1

所有方案的总曼哈顿距离之和为: 8

运行实例三

pls input m,n,k=1,4,4

以字符形式形成的方案: ['1111']

字符串方案转换为坐标列表方案: [[[0, 0], [0, 1], [0, 2], [0, 3]]]

正在处理坐标方案[[0, 0], [0, 1], [0, 2], [0, 3]],曼哈顿距离之和为10

所有方案的总曼哈顿距离之和为: 10

运行实例四

pls input m,n,k=5,1,5

以字符形式形成的方案: ['11111']

字符串方案转换为坐标列表方案: [[[0, 0], [1, 0], [2, 0], [3, 0], [4, 0]]]

正在处理坐标方案[[0, 0], [1, 0], [2, 0], [3, 0], [4, 0]],曼哈顿距离之和为20

所有方案的总曼哈顿距离之和为: 20

感悟:

将大问题分解为小问题,将数据处理成自己想要的形式,构建数据为解决问题服务,问题的解决将变得有迹可循,富于条理。


http://www.kler.cn/a/512749.html

相关文章:

  • JDBC实验测试
  • HarmonyOS NEXT:华为分享-碰一碰开发分享
  • 记一次常规的网络安全渗透测试
  • 记一次数据库连接 bug
  • TongESB7.1.0.0如何使用dockercompose运行镜像(by lqw)
  • 基础入门-传输加密数据格式编码算法密文存储代码混淆逆向保护安全影响
  • Elasticsearch(ES)基础查询语法的使用
  • spring Ioc 容器的简介和Bean之间的关系
  • 一文大白话讲清楚webpack基本使用——4——vue-loader的配置和使用
  • AI编程工具横向评测--Cloudstudio塑造完全态的jupyter notebook助力数据分析应用开发
  • Java基于SSM框架的社区团购系统小程序设计与实现(附源码,文档,部署)
  • xiaozhi-esp32 - 基于 ESP32 的 AI 聊天机器人
  • 2024年博客之星主题创作|Android 开发:前沿技术、跨领域融合与就业技能展望
  • 深入探索 Vue.js 的局部状态管理技术:基于 Pinia 的组合式 API 实现
  • Java程序运行剖析(JVM+JDK+JRE)(总结+超详解)
  • Python中字符串的基本操作
  • C#/.NET/.NET Core技术前沿周刊 | 第 22 期(2025年1.13-1.19)
  • Spring Boot拦截器:掌握Web请求的“守门员”
  • C++: Dtrees:load(constg String filepath, const String nodeName)中nodeName参数含义
  • “深入浅出”系列之C++:(15)simple_enum库
  • apache-zeppelin 命令执行 (CNVD-2019-33156)
  • Spring的循环依赖
  • ERROR:This version of pnpm requires at least Node.js vXXX 的解决方案
  • QT:子控件VLC播放视频时,父控件无法截取鼠标事件
  • 2025.1.16——五、LoveSQL1 sqlmap文件类|万能密码
  • Text2Sql:开启自然语言与数据库交互新时代(30/30)