PTA L2-007 家庭房产(解题思路)

文章介绍了如何利用并查集数据结构解决一个关于家庭成员及其房产问题,通过合并和查找操作,找出每个家庭的最小编号,同时计算平均房产数量和面积。
摘要由CSDN通过智能技术生成

并查集,用并查集的好处是题目中要求找出最小的下标,并查集需要用一个特征来表示唯一的祖先

需要 fa数组表示各编号的祖先,一个set集合用来记录所有出现过的人的编号,然后就是一个够大的数组记录房产信息(这里其实可以完全不用数组,用一个map编号直接映射房产信息的结构体就完了,这更节省空间),用并查集写很方便的地方在于不用创建很大的数组(除了fa数组),还有就是只需要遍历所有编号就能得出所有结果了,遍历的顺序对结果没有任何影响,因为只要是一个家族里面的,其祖先就是唯一的(最小的那个下标)

代码

import java.util.*;

public class Main {
    public static  class UnionQuerySet {
        static int[] arr = new int[10100];
        public static int find(int i){
            if(arr[i] == i){
                return i;
            }
            else{
                return find(arr[i]);
            }
        }
        public static void union(int i, int j){
            int f1 = find(i);
            int f2 = find(j);
            if(f1 > f2){
                arr[f1] = f2;
            }
            else{
                arr[f2] = f1;
            }
        }

        public static void init()
        {
            for(int i = 0; i < arr.length; i++){
                arr[i] = i;
            }
        }
        public static void main(String[] args) {
            init();

            for(int i = 0; i < arr.length - 3; i+=2){
                union(i, i+2);
            }
            for(int i = 1; i < arr.length-2; i+=2){
                union(i, i+2);
            }

            Map<Integer, List<Integer>> map = new HashMap<>();
            for(int i = 0; i < arr.length; i++){
                int root = find(i);
                if(map.containsKey(root)){
                    List<Integer> lst = map.get(root);
                    lst.add(i);
                }
                else{
                    List<Integer> lst = new ArrayList<>();
                    lst.add(i);
                    map.put(root,lst);
                }
            }

            for(Map.Entry<Integer,List<Integer>> entry : map.entrySet()){
                System.out.println(entry.getKey() + ":" + entry.getValue());
            }
        }
    }

    public static class FamilyInfo implements Comparable<FamilyInfo>{
        //    家庭成员的最小编号 家庭人口数 人均房产套数 人均房产面积
        private int mid;
        private int people_num;
        private int house_num_per_person;
        private double avg_area;

        public FamilyInfo(int mid, int people_num, int house_num_per_person, double avg_area) {
            this.mid = mid;
            this.people_num = people_num;
            this.house_num_per_person = house_num_per_person;
            this.avg_area = avg_area;
        }

        public int getMid() {
            return mid;
        }

        public void setMid(int mid) {
            this.mid = mid;
        }

        public int getPeople_num() {
            return people_num;
        }

        public void setPeople_num(int people_num) {
            this.people_num = people_num;
        }

        public int getHouse_num_per_person() {
            return house_num_per_person;
        }

        public void setHouse_num_per_person(int house_num_per_person) {
            this.house_num_per_person = house_num_per_person;
        }

        public double getAvg_area() {
            return avg_area;
        }

        public void setAvg_area(double avg_area) {
            this.avg_area = avg_area;
        }

        @Override
        public int compareTo(FamilyInfo o) {
            if(this.avg_area/this.people_num > o.avg_area/o.getPeople_num()){
                return -1;
            }
            else if(this.avg_area/this.people_num < o.avg_area/o.getPeople_num()){
                return 1;
            }
            else {
                return this.mid - o.mid;
            }
        }
    }

    public static class HouseInfo {
        private int house_num;
        private int total_area;

        public HouseInfo(int house_num, int total_area) {
            this.house_num = house_num;
            this.total_area = total_area;
        }

        public int getHouse_num() {
            return house_num;
        }

        public void setHouse_num(int house_num) {
            this.house_num = house_num;
        }

        public int getTotal_area() {
            return total_area;
        }

        public void setTotal_area(int total_area) {
            this.total_area = total_area;
        }
    }

    public static void main(String[] args) {
        UnionQuerySet.init();
//        10
//2333 -1 3721 3 6661 6662 6663 1 100
        Set<Integer> personSet = new HashSet<>();
        Scanner scanner = new Scanner(System.in);
        int num = scanner.nextInt();
        scanner.nextLine();
        Map<Integer, HouseInfo> map = new HashMap<>();
        for (int i = 0; i < num; i++) {
            String line = scanner.nextLine();
            String[] info = line.split(" ");
            int person_id = Integer.parseInt(info[0]);
            int father_id = Integer.parseInt(info[1]);
            int mother_id = Integer.parseInt(info[2]);
            int child_num = Integer.parseInt(info[3]);
            int house_num = Integer.parseInt(info[info.length - 2]);
            int total_area = Integer.parseInt(info[info.length - 1]);
            HouseInfo houseInfo = new HouseInfo(house_num, total_area);
            personSet.add(person_id);
            if (father_id != -1) {
                UnionQuerySet.union(person_id, father_id);
                personSet.add(father_id);
            }
            if (mother_id != -1) {
                UnionQuerySet.union(person_id, mother_id);
                personSet.add(mother_id);
            }
            for(int j = 0; j < child_num; j++){
                int child_id = Integer.parseInt(info[4+j]);
                UnionQuerySet.union(person_id, child_id);
                personSet.add(child_id);
            }

            map.put(person_id, houseInfo);
        }
        Map<Integer, FamilyInfo> map2 = new HashMap<>();
        for(Integer pId : personSet){
            int root = UnionQuerySet.find(pId);
            if(map2.containsKey(root)){
                FamilyInfo familyInfo = map2.get(root);
                int house_num_per_person = 0;
                double avg_area = 0;
                if(map.containsKey(pId)){
                    house_num_per_person = map.get(pId).getHouse_num();
                    avg_area = map.get(pId).getTotal_area();
                }
                familyInfo.setPeople_num(familyInfo.getPeople_num() + 1);
                familyInfo.setHouse_num_per_person(familyInfo.getHouse_num_per_person()+house_num_per_person);
                familyInfo.setAvg_area(familyInfo.getAvg_area()+avg_area);
//                map2.put(root, familyInfo);
            }
            else{
                int house_num_per_person = 0;
                double avg_area = 0;
                if(map.containsKey(pId)){
                    house_num_per_person = map.get(pId).getHouse_num();
                    avg_area = map.get(pId).getTotal_area();
                }
                FamilyInfo familyInfo = new FamilyInfo(root, 1, house_num_per_person, avg_area);
                map2.put(root, familyInfo);
            }
        }
        List<FamilyInfo> familyInfoList = new ArrayList<>();
        for(Map.Entry<Integer, FamilyInfo> entry : map2.entrySet()){
            familyInfoList.add(entry.getValue());
        }
        Collections.sort(familyInfoList);
        System.out.println(familyInfoList.size());
        for(FamilyInfo familyInfo : familyInfoList){
            System.out.print(String.format("%04d",familyInfo.getMid()));
            System.out.print(" "+familyInfo.getPeople_num()+" ");
            System.out.printf("%.3f",familyInfo.getHouse_num_per_person()*1.0/familyInfo.getPeople_num());
            System.out.print(" ");
            System.out.printf("%.3f", familyInfo.getAvg_area()/familyInfo.getPeople_num());
            System.out.println();
        }
    }
}

  • 26
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值