演算法題之裝空調

Dennis_Ritchie發表於2020-05-21

前言

昨天看到一個演算法題,挺有意思的,大家分享下,這道題被定義為困難。

題目

學校要裝空調了!!!

9102年,學校終於要裝空調了,學生們都歡呼雀躍的期待著學校趕緊把空調裝好。但是學校招過來的安裝空調的人卻不夠了,同一時間只能安裝一個空調,這引起了大家的不滿。大家都希望學校能夠先裝自己宿舍,如果裝的太晚就要抗議。

假設學校共有 n 棟宿舍樓,每棟宿舍樓有 m 間宿舍,每間宿舍都有大小不同的忍受度。學校裝空調時,只能把同一棟樓的空調安裝完畢後才能安裝其他宿舍樓的空調。

作為校長精明能幹的助手,校長希望你能夠安排好學校安裝空調的順序,讓抗議的宿舍數最少。(增添人手的錢都用來買空調了,別想在招人了)

入參有三個,第一個輸入一個整數n,表示n棟宿舍樓;
第二個輸入一個整數m,表示每棟樓有m間宿舍;
接下來輸入一個n*m的矩陣,表示每棟宿舍樓的每間宿舍的忍受度f(ij)。
(1 <= n <=20 ,1<=m <=1000,1<=f(ij)<=n *m)。

註釋:忍受度:如果某個宿舍宿舍是所有宿舍(包含其他宿舍樓的宿舍)中第 x 個裝空調的(x > f_{ij}) , 那麼這個宿舍就要去抗議。
輸出最少的抗議的宿舍數。

示例1

輸入:
3
3
[[3,1,2],[6,5,8],[7,3,4]]
輸出:
2
注意
安裝空調的順序依次為:


(1,2)(1,3)(1,1)
(2,2)(2,1)(2,3)
(3,1)(3,2)(3,3)

實現程式碼

package solution70;

import java.util.ArrayList;
import java.util.Comparator;
import java.util.List;

public class Solution {
    private int minCount = Integer.MAX_VALUE;
    private int position = 0;//from 1
    private int currentCount = 0;
    private List<Floor> floors;
    private int n;
    private int m;
    private List<Room> orderedRooms = new ArrayList<>();

    public int solution(int n, int m, int[][] f) {
        initData(n, m, f);
        this.start();
        return minCount;
    }

    private void initData(int n, int m, int[][] f) {
        this.n = n;
        this.m = m;
        int i = 0;
        int j;
        ArrayList<Floor> floors = new ArrayList<>();
        for (; i < n; i++) {
            ArrayList<Room> rooms = new ArrayList<>();
            for (j = 0; j < m; j++) {
                rooms.add(new Room(false, f[i][j], i + 1, j + 1));
            }
            sortRooms(rooms);
            Floor floor = new Floor(false, rooms);
            floors.add(floor);
        }
        this.floors = floors;
    }

    private void sortRooms(List<Room> rooms) {
        rooms.sort(new Comparator<Room>() {
            @Override
            public int compare(Room o1, Room o2) {
                return o1.getEndurance() - o2.getEndurance();
            }
        });
    }

    private void start() {
        boolean allChecked = true;
        FloorResult result;
        for (Floor f :
                floors) {
            if (!f.isChecked()) {
                f.setChecked(true);
                result = calculateFloor(f);
                allChecked = false;
                position -= result.getIterateCount();
                currentCount -= result.getCount();
                f.setChecked(false);
            }
        }
        //the last floor
        if (allChecked) {
            if (currentCount < minCount) {
                minCount = currentCount;
                printRoom();
            }
            System.out.println("min:" + minCount + " and now:" + currentCount);
        }
    }

    private void printRoom() {
        for (Floor f :
                this.floors) {
            System.out.println("-----------------");
            for (Room m :
                    f.getRooms()) {
                System.out.println("(" + m.getPosition() + "," + m.getEndurance() + ")");
            }
            System.out.println("-----------------");
        }
    }

    private FloorResult calculateFloor(Floor floor) {
        boolean afterShouldProtest = false;
        FloorResult result = new FloorResult();
        int reservedPosition;
        int reservedCount;
        boolean isFound = false;
        // List<Room> cur = new ArrayList<>();
        for (Room r :
                floor.getRooms()) {
            if (!r.isChecked()) {
                result.incrIterateCount();
                position++;
                r.setChecked(true);
                isFound = false;
                //cur.add(r);
                if (r.getEndurance() < position) {
                    for (Room m :
                            floor.getRooms()) {
                       /* boolean checked = m.isChecked();
                        m.setChecked(true);*/
                        if (!m.isChecked() && m.getEndurance() >= position) {
                            //skip
                            m.setChecked(true);
                            isFound = true;
                            m.setPosition(position);
                            break;
                        }
                    }
                    r.setPosition(0);
                    currentCount++;
                    result.incrCount();
                    if (!afterShouldProtest) {
                        afterShouldProtest = true;
                    }
                    if (currentCount >= minCount) {
                        //restore
                        for (Room k :
                                floor.getRooms()) {
                            k.setChecked(false);
                        }
                        return result;
                    }
                } else {
                    r.setPosition(position);
                }
            }
        }
        //restore
        for (Room r :
                floor.getRooms()) {
            r.setChecked(false);
        }
        reservedPosition = position;//reserve
        reservedCount = currentCount;
        //next floor
        start();
        position = reservedPosition;
        currentCount = reservedCount;
        return result;
    }

    private static class Floor {
        private boolean isChecked;
        private List<Room> rooms;

        public Floor(boolean isChecked, List<Room> rooms) {
            this.isChecked = isChecked;
            this.rooms = rooms;
        }

        public boolean isChecked() {
            return isChecked;
        }

        public void setChecked(boolean checked) {
            isChecked = checked;
        }

        public List<Room> getRooms() {
            return rooms;
        }

        public void setRooms(List<Room> rooms) {
            this.rooms = rooms;
        }

        public void addRoom(Room room) {
            rooms.add(room);
        }
    }

    private static class Room {
        private boolean isChecked;
        private int endurance;
        private int x;
        private int y;
        private int position;

        public Room(boolean isChecked, int endurance, int x, int y) {
            this.isChecked = isChecked;
            this.endurance = endurance;
            this.x = x;
            this.y = y;
        }

        public boolean isChecked() {
            return isChecked;
        }

        public void setChecked(boolean checked) {
            isChecked = checked;
        }

        public int getEndurance() {
            return endurance;
        }

        public void setEndurance(int endurance) {
            this.endurance = endurance;
        }

        @Override
        public String toString() {
            return "Room{" +
                    "isChecked=" + isChecked +
                    ", endurance=" + endurance +
                    ", x=" + x +
                    ", y=" + y +
                    '}';
        }

        public int getPosition() {
            return position;
        }

        public void setPosition(int position) {
            this.position = position;
        }
    }

    private static class FloorResult {
        private int iterateCount;
        private int count;

        public FloorResult() {
        }

        public FloorResult(int iterateCount, int count) {
            this.iterateCount = iterateCount;
            this.count = count;
        }

        public int getIterateCount() {
            return iterateCount;
        }

        public void setIterateCount(int iterateCount) {
            this.iterateCount = iterateCount;
        }

        public int getCount() {
            return count;
        }

        public void setCount(int count) {
            this.count = count;
        }

        public void incrIterateCount() {
            iterateCount++;
        }

        public void incrCount() {
            count++;
        }
    }
}
本作品採用《CC 協議》,轉載必須註明作者和本文連結

如果有不懂的地方,可以加我的qq:1174332406,或者是微信:itshardjs

相關文章