[解题报告]Maximum Students Taking Exam

题目链接
给定一个教室图,“.”表示有一个座位,“#”表示没有座位
要求座位左前、右前、左边、右边四个方向座位均无人时才可坐下
求给定教室最多能坐几个人

状态压缩动态规划,因为每个座位是否可坐取决于当前排前一排,因此对每排座位布局进行状态压缩
数据范围8 * 8,所以最多2 ^ 8 = 256种状态

状态转移方程:
dp[i][j] = max(dp[i][j], dp[i - 1][k] + CountBinary1(j))
其中i表示第几排
j、k表示该排座位状态压缩后的值
j、k布局应当满足题目要求

时间复杂度
O(N * (2 ^ (2 * M)))
Runtime: 0 ms beats 100%
Memory Usage: 2.2 MB

func maxStudents(seats [][]byte) (ans int) {
	if len(seats) == 0 || len(seats[0]) == 0 {
		return 0
	}
	m := len(seats)
	n := len(seats[0])

	dp := make([][]int, m)

	for i := range dp { // 状态需要2 ^ len的长度
		dp[i] = make([]int, int(math.Pow(2, float64(n))))
	}

	byteSeats := make([]int, m)

	for i := range byteSeats {
		for j := range seats[i] { // 按位压缩每一行的座椅位置
			byteSeats[i] <<= 1
			if seats[i][j] == '.' {
				byteSeats[i] += 1
			}
		}
	}

	max := func(a, b int) int {
		if a > b {
			return a
		}
		return b
	}

	cnt1 := func(v int) (ans int) { // 计算一个int里二进制表示有多少个1
		for ; v != 0; v >>= 1 {
			if v & 1 == 1 {
				ans++
			}
		}
		return
	}

	for i := 0; i < m; i++ {
		for j := 0; j < (1 << uint(n)); j++ {
			if j | byteSeats[i] != byteSeats[i] || // 不是需要的座位组合
				j & (j << 1) != 0 { // 邻座有人
				continue
			}

			for k := 0; k < (1 << uint(n)); k++ {
				if i == 0 {
					dp[i][j] = cnt1(j)
					break
				}
				if k | byteSeats[i - 1] != byteSeats[i - 1] ||
					k & (k << 1) != 0 ||
					((j << 1) & k) != 0 || // 两种情况分别是左前方右前方是否有人坐下
					((j >> 1) & k) != 0 {
					continue
				}
				dp[i][j] = max(dp[i][j], dp[i - 1][k] + cnt1(j))
			}
		}
	}

	for i := 0; i < (1 << uint(n)); i++ {
		if dp[m- 1][i] > ans {
			ans = dp[m- 1][i]
		}
	}

	return
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值