白板演示攻破算法难题
本题算法思路视频讲解请点击——> b站鲁班代师讲解视频
如链接失效以及获取更多精彩视频(Letecode笔试高频题、互联网大厂笔试刷题)请在bilibili搜索鲁班代师,然后搜索题号关键字就可以了,关注不走丢,感谢。
欢迎批评指正、探讨!
关键思路
- 坏椅分布二进制代码化
- 从第1行开始安排学生分布
(1) 遍历求解第i行状态
(2) 考虑自身冲突:左右冲突、坏椅冲突
(3) 考虑前后行冲突:左上、右上不能坐人的冲突 - 无冲突的位置,计算dp矩阵
dp[i][c] = max(dp[i][c],dp[i-1][l] + 第i行的人数即c中1的个数) - 返回dp矩阵第m行最大的值
代码
package com.Test.GdTest;
public class Main02
{
public static void main(String[] args) {
char[][] arr = {{'#','.','#','#','.','#'},{'.','#','#','#','#','.'},{'#','.','#','#','.','#'}};
Solution s = new Solution();
int max = s.maxStudents(arr);
System.out.println(max);
}
}
class Solution {
public int maxStudents(char[][] seats) {
int m = seats.length;//行数
int n = seats[0].length;//列数
//标记坏椅,坏标1,s[i]代表第i行的坏椅子情况
int[] s = new int[m + 1];
for(int i = 1; i <= m; i ++)
{
for(int j = 0; j < n; j ++)
{
if(seats[i-1][j] == '#')
{
s[i] = s[i] | (1 << n-j-1);
}
}
}
//dp数组,dp[i][j]表示第i行安排j个学生,前i行最多学生数
int[][] dp = new int[m + 1][1 << n];
int ans = 0;
for(int i = 1; i <= m; i++)
{
//第i行状态遍历
for(int c = 0; c < (1 << n); c++)
//for(int c = 0; c < n; c++)
{
//判断当前行是否可行,是否有单行冲突,有则跳过
if(((c & (c >> 1)) != 0) || ((c & s[i]) != 0))
{
continue;//有仁一冲突,跳出循环
}
//查看当前第i行有c个学生的情况,第i-1行的各种情况是否有冲突
for(int l = 0; l < (1 << n); l++)
//for(int l = 0; l <= n; l++)
{
//1.判断i-1行自身是否冲突(左右+坏椅)
//2.判断左上、右上是否冲突
if(((l & (l >> 1)) == 0) && ((l & s[i-1]) == 0) && (((c << 1) & l) == 0) && (((c >> 1) & l) == 0))
{
dp[i][c] = Math.max(dp[i][c], dp[i-1][l] + countOne(c));
}
}
}
}
for(int i = 0; i < (1 << n); i++)
{
ans = Math.max(dp[m][i], ans);
}
return ans;
}
//判断当前数x中1的个数
public int countOne(int x)
{
int count = 0;
while(x != 0)
{
x = x & (x-1);
count ++;
}
return count;
}
}