1.题目:参加考试的最大学生数
2. 自身想法
只知道可能跟动态规划有关
座位的状态包含两种,一种是坐了,另一种是没坐。并且如果(i,j)
选择坐了,那么(i,j-1)
、(i,j+1)
、(i+1,j-1)
、(i+1,j+1)
这四个点就不可以选,不然(i,j)
会被暴露
然后,还是没有做出来,找不到前一个状态和后一个状态的关系
3. 官方解法
设计到位运算,刚开始有点不理解,之后按照它的代码,全部走下来就可以ok了,主要记录一下,关于代码理解过程中涉及到的点。
思路:
-
以排为单位,用
status
记录这一排的状态,官解这边用了二进制,1
表示坐,0
表示没坐。例如:status=2
,二进制就是00000010
表示1
的这个位置是有学生的,那么可以看出这status
可以用循环变量来表示 -
某一排之间是由限制的,如
#
的位置不可以有学生,以及坐了学生的位子两边不可以有学生。这个限制由isSingleRowCompliant
这个函数来验证 -
排与上一排之间是由关系的,如
row
排的(i,j)
有学生,则row-1
排的(i-1,j-1)
以及(i-1,j+1)
不可以有学生。这个限制由isCrossRowsCompliant
这个函数来验证。isCrossRowsCompliant(status,upperStatus,n)
-
关于
dp(seats,row,status)
函数的作用,是表示到row
排状态为status
时,最大的学生数。里面会用到以上两个函数,但是用到isCrossRowsCompliant
这个函数的时候,还涉及到upperStatus
,也就是上一排的状态 ,这必然就会有遍历上一个状态的过程(i++)
,并且记录一下最大值,并返回。官解,这把这个状态对于上一个状态的最大值记录在map当中,key
包含了row
和status
这两个点的信息,value
就是当前状态status
对于上个状态的最大学生数 -
最后一步,就是调用
dp(seats,m-1,i)
函数
4. 小知识点
因为这边涉及到位运算,用每一位来表示座位的状态,就要涉及到求解状态中1
的个数,这里用到Integer.bitCount(status);//二进制补码中1的位数,就是元素的个数
来统计