力扣刷题之 黑白方格画

LCP 22. 黑白方格画



一、题目描述

已知:画板上有 n * n 的网格。绘画规则为,可以选择任意多行以及任意多列的格子涂成黑色(选择的整行、整列均需涂成黑色),所选行数、列数均可为 0。

要求:最终的成品上需要有 k 个黑色格子,请返回共有多少种涂色方案。

注意:两个方案中任意一个相同位置的格子颜色不同,就视为不同的方案。

限制: 1 <= n <= 6
0 <= k <= n * n
原题链接:黑白方格画


二、问题分析

设网格上已经涂了 x 行 y 列,考虑到行列之间有一个重复格子,因此网格上的黑格子数目为 n*(x+y) - x*y。

即求解下列方程式,可能的(x, y)有多少种
n*(x+y) - x*y = k

由于 1 <= n <= 6 并且 0 <= x, y <= n
所以可以暴力穷举,计算得到可能的 (x,y) 值。

进一步,由于涂的行/列可以在 n 行/列中自由进行选择,
所以涂色的方案总共有:
C(n, x) * C(n, y)


三、数据结构及算法分析

1.数据结构

2.涉及算法

主要是 C(n, x) 的计算如何用代码实现。

C(n, x) = [n * (n-1) *… (n-x+1)] / [1 * 2 *… x]

代码实现如下:

def get(n, a):
	res = 1
	for i in range(n, n-a, -1):
		res *= i
	for j in range(1, a+1):
		res /= j
	return res

时间复杂度:O(n)
空间复杂度:O(1)


四、总结

结题思路主要分为两个步骤:
一、穷举计算方程式 n*(x+y) - x*y = k,计算得到需要涂多少行和列
二、具体到涂网格的哪一行哪一列,根据组合排列的知识,计算可能有多少种涂色方案


五、完整源码

class Solution:
    def paintingPlan(self, n: int, k: int) -> int:
        if k in (0, n * n):
            return 1
        def get(n, a):
            res = 1
            for i in range(n, n-a, -1):
                res *= i
            for j in range(1, a+1):
                res /= j
            return res
        ans = 0
        for x in range(n):
            for y in range(n):
                if n*(x+y) - x*y == k:
                    ans += get(n, x) * get(n, y)
        return int(ans)

时间复杂度:O(n2)
空间复杂度:O(1)


一 起 前 进
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值