zoukankan      html  css  js  c++  java
  • 动态规划-状态压缩-参加考试的最大学生数

    2020-02-29 22:18:12

    问题描述:

    问题求解:

    解法一:DFS

    将原问题转化成图的问题,使用dfs去遍历得到解。

    核心思想就是每次遍历到一个点,不仅将其标记为使用,还要将其周围的节点标记为访问过,避免之后遍历到矛盾的节点。

        int res = 0;
        
        public int maxStudents(char[][] seats) {
            List<int[]> pos = new ArrayList<>();
            for (int i = 0; i < seats.length; i++) {
                for (int j = 0; j < seats[0].length; j++) {
                    if (seats[i][j] == '.') pos.add(new int[]{i, j});
                }
            }
            for (int[] start : pos) {
                Set<int[]> used = new HashSet<>();
                res = Math.max(res, dfs(pos, start, used));
            }
            return res;
        }
        
        private int dfs(List<int[]> pos, int[] start, Set<int[]> used) {
            if (used.contains(start)) return 0;
            used.add(start);
            for (int[] next : pos) {
                if (check(next, start) || check(start, next)) used.add(next);
            }
            int res = 1;
            for (int[] next : pos) {
                if (used.contains(next)) continue;
                res += dfs(pos, next, used);
            }
            return res;
        }
        
        private boolean check(int[] p1, int[] p2) {
            if (p1[0] == p2[0] && p1[1] == p2[1] - 1) return true;
            if (p1[0] == p2[0] && p1[1] == p2[1] + 1) return true;
            if (p1[0] == p2[0] - 1 && p1[1] == p2[1] - 1) return true;
            if (p1[0] == p2[0] - 1 && p1[1] == p2[1] + 1) return true;
            return false;
        }

    解法二:DP

    本题最优的解法是DP,采取的思路是当前行的状态只和上一行相关,因此如果我们遍历上下行的所有状态,从中挑选出符合条件的状态,就可以得到解。

    本题的思路和开关灯泡的搜索解有异曲同工的地方。

        public int maxStudents(char[][] seats) {
            int m = seats.length;
            int n = seats[0].length;
            int[] broken = new int[m + 1];
            for (int i = 0; i < m; i++) {
                int state = 0;
                for (int j = 0; j < n; j++) {
                    if (seats[i][j] == '#') state |= (1 << j);
                }
                broken[i + 1] = state;
            }
            int[][] dp = new int[m + 1][1 << n];
            for (int i = 1; i <= m; i++) {
                for (int u = 0; u < (1 << n); u++) {
                    if ((u & (u >> 1)) != 0 || (u & broken[i - 1]) != 0) continue;
                    for (int v = 0; v < (1 << n); v++) {
                        if ((v & (v >> 1)) != 0 || (v & broken[i]) != 0 ||(v & (u >> 1)) != 0 || (v & (u << 1)) != 0) continue;
                        dp[i][v] = Math.max(dp[i][v], dp[i - 1][u] + helper(v));
                    }
                }
            }
            int res = 0;
            for (int i = 0; i < (1 << n); i++) res = Math.max(res, dp[m][i]);
            return res;
        }
        
        private int helper(int num) {
            int res = 0;
            for (int i = 0; i < 32; i++) if ((num & (1 << i)) != 0) res += 1;
            return res;
        }
    

    解法三:DP + 子集枚举

        public int maxStudents(char[][] seats) {
            int m = seats.length;
            int n = seats[0].length;
            int[] states = new int[m + 1];
            for (int i = 0; i < m; i++) {
                int state = 0;
                for (int j = 0; j < n; j++) {
                    if (seats[i][j] == '.') state |= (1 << j);
                }
                states[i + 1] = state;
            }
            int[][] dp = new int[m + 1][1 << n];
            for (int i = 1; i <= m; i++) {
                for (int u = states[i - 1];; u = (u - 1) & states[i - 1]) {
                    for (int v = states[i];; v = (v - 1) & states[i]) {
                        if ((u & (u >> 1)) == 0 && (v & (v >> 1)) == 0 && (v & (u >> 1)) == 0 && (v & (u << 1)) == 0) dp[i][v] = Math.max(dp[i][v], dp[i - 1][u] + helper(v));
                        if (v == 0) break;
                    }
                    if (u == 0) break;
                }
            }
            int res = 0;
            for (int i = states[m];; i = (i - 1) & states[m]) {
                res = Math.max(res, dp[m][i]);
                if (i == 0) break;
            }
            return res;
        }
        
        private int helper(int num) {
            int res = 0;
            for (int i = 0; i < 32; i++) if ((num & (1 << i)) != 0) res += 1;
            return res;
        }
    

      

      

  • 相关阅读:
    站立会议08
    站立会议07
    站立会议06
    站立会议05
    SOA架构设计的案例分析
    java实现根据高德地图API接口进行地址位置解析,将地址转化为经纬度
    java实现根据起点终点和日期查询去哪儿网的火车车次和火车站点信息
    Cocos2d切换场景出现的问题-error C2653: “***”不是类或命名空间名称
    云时代架构之点融支付系统架构的演进
    云时代架构之百度万人协同规模下的代码管理架构演进
  • 原文地址:https://www.cnblogs.com/hyserendipity/p/12386649.html
Copyright © 2011-2022 走看看