zoukankan      html  css  js  c++  java
  • LeetCode LCP 29. 乐团站位

    LCP 29. 乐团站位

    绕远路

    为了我自己看起来舒服, 以下x``y坐标的定义与题目相反

    彩笔如我, 看着题目题目描述需要环绕排序, 结果一不注意调起了自动脑补, 瞬间拆成分情况讨论...

    然鹅这并不优雅, 姑且先记下来嘲笑过去的自己

    为了坐标算起来方便, 位置起点为0, 每轮i拆解一次外层(半圈), 然后触发自动脑补机制逆时针旋转180°....

    此时得到每轮起点位置与终点位置对应关系

    i st add ed
    0 0 2(n-1) 2(n-1)
    1 2(n-1) + 1 2(n-2) 2(2n-1-2) + 1
    2 2(2n-1-2) + 2 2(n-3) 2(3n-1-2-3) + 2
    ... ... ... ...
    i 2(in- i*(i+1)/2) + i 2(n-1-i) 2((i+1)n - (i+2)(i+1)/2) + i
    ... ... ... ...
    i i(2n-i) ... i(2n-i-2) + 2n-2

    已知每段长度, 为方求(y, x)具体位置, 则需利用每段的起点/终点计算。因为每次只拆解半圈, 所以计算位置时只会发生横纵其中一个坐标的变动。(你这大脑是有多懒?

    接下来则列出每轮拆解的起点/终点, [st(y,x), ed(y,x)]

    i st(y,x) ed(y,x)
    0 (0, 0) (n-1, n-1)
    1 (n-1, n-2) (1, 0)
    2 (1, 1) (n-2, n-2)
    3 (n-2, n-3) (3, 2)
    ... ... ...
    i (i/2, i/2) (n-1 - i/2, n-1 - i/2)
    i (n-1 - (i-1)/2, n-2 - (i-1)/2) (i, (i+1)/2)
    ... ... ...
    i (i/2, i/2) (n-1 - i/2, n-1 - i/2)
    i (n - (i+1)/2, n - (i+3)/2) (i, (i+1)/2)

    此时得到(y, x)i的对应关系, 但肉眼可见地出现了奇偶差异(更麻烦了, 喂!

    于是根据不同区域, 上u, 右r, 下d, 左l, 进行分情况讨论...

    区域 限制条件
    u x=>y && x<n-y
    r x=>y && x>=n-y
    d x<y && x>=n-1-y
    l x<y && x<n-y

    最后, 根据条件按已列出的关系从下往上带入就能得到答案..._(ˊཀˋ」∠)_

    Python3

    class Solution:
        def orchestraLayout(self, num: int, xPos: int, yPos: int) -> int:
            x, y = yPos, xPos
            if x>=y and x<num-y:
                i = y*2
                st = i*(2*num-i)
                p = st + x-y
                return (p%9) + 1
            if x>=y and x>=num-y:
                i = (num-1 - x)*2
                ed = i*(2*num-i-2) + 2*num-2
                p = ed - (x-y)
                return (p%9) + 1
            if x<y and x>=num-1-y:
                i = 2*(num-y) - 1
                st = i*(2*num-i)
                p = st + y-1-x
                return (p%9) + 1
            if x<y and x<num-y:
                i = 2*x + 1
                ed = i*(2*num-i-2) + 2*num-2
                p = ed - (y - (x+1))
                return (p%9) + 1
            return -1
    

    理论上

    其实没必要每次拆半圈, 直接拆一整圈更方便。

    于是乎, 将矩形分为2个部分, 其一是若干层完整的外环, 其二为(x, y)所在环的格子数。

    外环 = 完整矩形 - 内部矩形

    (x, y)的格子占用计算需要拆分为y>=xy<x两种情况, 这样x, y各自单调, 方便计算。(可作图观察到, 此处身略

    为了方便描述, 定义a(x, y)所在位置与最外层的层数差, 可以简单认为a=min(x, y, n-1-x, n-1-y), 不过因为多了xy的限定条件可以一同拆分。

    根据以上分情况讨论, 得到位置函数f(x, y)如下

    [egin{aligned} f(x, y) &= egin{cases} n^2-(n-2a)^2 + (x+y-2a) &y>=x \ n^2 - [n-2(a+1)]^2 - (x+y-2a) &y<x end{cases} \ a &= egin{cases} min(x, n-1-y) &y>=x \ min(y, n-1-x) &y<x end{cases} end{aligned}]

    此时已能得到答案, 不够由于强迫症发作, 故尝试整合表达式...

    分解多项式后可以得到如下两个式子

    [ f(x, y) = egin{cases} 4na - 4a^2 - 2a &+ (x+y) \ 4na - 4a^2 - 2a &- (x+y) + (4n-4a-4) end{cases} ]

    增加两个变量b,c, 整合表达式

    [egin{aligned} f(x, y) &= 4na - 4a^2 - 2a + b(x+y) + c(4n-4a-4) \ a &= egin{cases} min(x, n-1-y) &y>=x \ min(y, n-1-x) &y<x end{cases} \ b &= egin{cases} 1 &y>=x \ -1 &y<x \ end{cases} \ c &= egin{cases} 0 &y>=x \ 1 &y<x end{cases} end{aligned}]

    再借助位运算完成1->0, -1->1的转换

    得到最终表达式如下

    [egin{aligned} f(x, y) &= 4na - 4a^2 - 2a + b(x+y) + (b gg 1&1)(4n-4a-4) \ a &= egin{cases} min(x, n-1-y) &y>=x \ min(y, n-1-x) &y<x end{cases} \ b &= egin{cases} 1 &y>=x \ -1 &y<x \ end{cases} end{aligned}]

    Python3

    class Solution:
        def orchestraLayout(self, num: int, xPos: int, yPos: int) -> int:
            a, b = (min(xPos, num-1-yPos), 1) if yPos >= xPos else (min(yPos, num-1-xPos), -1)
            return (4*num*a - 4*a*a - 2*a + b*(xPos+yPos) + (b>>1&1)*4*(num-a-1))%9 + 1
    
  • 相关阅读:
    springboot:快速构建一个springboot项目
    SpringBoot Unable to start EmbeddedWebApplicationContext due to missing EmbeddedServletContainerFactory bean.
    springboot添加swagger2组件
    Mysql实现企业级数据库主从复制架构实战
    方案优化:网站实现扫描二维码关注微信公众号,自动登陆网站并获取其信息
    网站实现扫描二维码关注微信公众号,自动登陆网站并获取其信息
    九度OJ 1402 特殊的数 -- 位操作
    九度OJ 1385 重建二叉树
    九度OJ 1386 旋转数组的最小数字 【算法】
    九度OJ 城际公路网 -- 图论
  • 原文地址:https://www.cnblogs.com/Simon-X/p/15488067.html
Copyright © 2011-2022 走看看