Leetcode 5335. 参加考试的最大学生数 状压DP

OJ

每一行只与上一行有关,看成二进制,同时每一行最多2^8种状态,我们自然想到进行状态压缩

状态转移方程为:

dp[row][state] = max(dp[row-1][last] + state.count())

其中state代表某一个二进制数字,state.count代表当前数字的二进制有多少个1

注意我们需要检查合法性,这里包括:

本行的合法性:不能把学生安排在坏座位上;不能有相邻的学生
两行之间的合法性:如果第一行某个位置安排了学生,则下一行斜向的两个位置不能安排学生
最后的结果就是

max(dp[m][state])

代码

public int maxStudents(char[][] seats) {
    int o[] = new int[256], f[][] = new int[9][256], a[] = new int[9];
    int n = seats.length, m = seats[0].length, i, j, k, ans = 0;
    for (i = 1; i < 256; i++)
        // o用来记录某个数的二进制有多少个1
        o[i] = o[i >> 1] + (i & 1);
    for (int[] ints : f) {
        Arrays.fill(ints, Integer.MIN_VALUE);
    }
    for (i = 0; i < n; i++)
        for (j = 0; j < m; j++)
            if (seats[i][j] == '#')
                // a用二进制表示教室状态
                a[i] |= 1 << j;
    for (i = f[0][0] = 0; i < n; i++)
    	// 遍历一行的可能的坐人状态
        for (j = 0; j < 1 << m; j++)
        	// 验证是否有人坐在坏椅子上,验证是否有人坐在相邻位置
            if ((j & a[i]) == 0 && (j & j >> 1) == 0 && (j & j << 1) == 0)
                for (k = 0; k < 1 << m; k++)
                	// 与相邻行是否冲突
                    if ((j & k >> 1) == 0 && (j & k << 1) == 0)
                        f[i + 1][j] = Math.max(f[i + 1][j], f[i][k] + o[j]);
    for (i = 0; i < 1 << m; i++)
        ans = Math.max(ans, f[n][i]);
    return ans;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值