• 杭电oj_2063——过山车(java实现)


    原题链接:

    http://acm.hdu.edu.cn/showproblem.php?pid=2063

    思路:

    一开始用贪心做:按每一个女孩子期望搭档的人的数量将数组排序,然后优先选择期望数量少的,但是在oj上WA了(没想通为啥不行,有会的大佬还望指点/拜托)

    然后就在网上看博客,看到大家都是用“匈牙利算法”做的,以前没听过,长知识了/捂脸

    总结匈牙利算法本身:优先选择候选数据的第一个,然后能让就让——让的意思是自己选取下一个,将原来的腾给新的请求者,如果自己都没得选了,则不让(貌似也是贪心的思想?)

    在网上找的博客地址:

    https://blog.csdn.net/pku_coder/article/details/53701327

    介绍完匈牙利算法,就讲讲在本题中如何应用的思路(其实这一题就是经典的匈牙利算法,都不用怎么变动的)

    1.先将数据接收

    • 创建一个used数组(用于在匈牙利算法中标记改人是否已经被查找过——也就是说选搭档的顺序只能顺着候选人往下,不能回头)
    • 创建一个boy数组(用于记录每一次的搭档情况)
    • 创建relation二维数组(用于存储女生期望搭档的映射图)

    2.开始扫描每一个女生,每个女生都通过一次匈牙利算法,如果返回为true,这说明可以腾出位置,则结果加一,否则接着循环(注:在一个女生结束之后,将used数组回溯,便于下一次查找)

    基本思路就是这样,也不知道说清楚没有/捂脸

    下面直接上源码(附有原贪心WA算法):

    package hduoj;
    
    import java.util.Scanner;
    ///**
    // * 使用贪心策略:
    // * 优先选择期望partner最少的
    // */
    //正解是使用匈牙利算法——最佳指配
    public class hdoj_2063 {
        private static int[][] relation_pic;
        private static int[] used;
        private static int[] boy;
        private static int girl_num;
        private static int boy_num ;
    
        public static void main(String[] args) {
            Scanner sc = new Scanner(System.in);
            while(true) {
                int count = sc.nextInt();
                if (count == 0) break;
                girl_num = sc.nextInt();
                boy_num = sc.nextInt();
                relation_pic = new int[girl_num + 1][boy_num + 1];
                used = new int[boy_num + 1];
                boy = new int[boy_num + 1];
                while (count-- != 0) {
                    int girl_no = sc.nextInt();
                    int boy_no = sc.nextInt();
                    relation_pic[girl_no][boy_no] = 1;
                }
    
                int res = 0;
                for(int i = 1;i<=girl_num;++i){
                    for(int j = 1;j<=boy_num;++j){
                        used[j] = 0;//将男同学恢复单身
                    }
                    if(find(i)){
                        res++;
                    }
                }
    
                System.out.println(res);
            }
        }
    
        private static boolean find(int girl_no){
            for(int i = 1;i <= boy_num;++i){//扫描每个男生
                if(relation_pic[girl_no][i]==1&&used[i]==0){
                    //若当前有暧昧关系且男生未被标记的话,则让其标记为已查找过
                    used[i] = 1;
                    if(boy[i] == 0 || find(boy[i])){
                        //若当前男生无搭档或者其搭档可以重新分配给别人的话,则返回true,表示找到新的分配组合
                        boy[i] = girl_no;
                        return true;
                    }
    
                }
            }
            return false;
        }
    
    
    
        //贪心做法失败
    //    public static void main(String[] args) {
    //        Scanner sc = new Scanner(System.in);
    //        while(true){
    //            int count = sc.nextInt();
    //            if(count == 0) break;
    //            int boy_num = sc.nextInt();
    //            int girl_num = sc.nextInt();
    //            Integer[][] combination = new Integer[girl_num + 1][];
    //
    //            int[] boy_flag = new int[boy_num + 1];
    //            for(int i = 0;i<=boy_num;++i){//用来标记已经被选中的男孩,0为被选中
    //                boy_flag[i] = 1;
    //            }
    //            HashMap<Integer,ArrayList<Integer>> hashmap = new HashMap<>();
    //            for(int i = 0;i<count;++i){
    //                int girl = sc.nextInt();
    //                int boy = sc.nextInt();
    //                if(hashmap.containsKey(girl)){
    //                    hashmap.get(girl).add(boy);
    //                }else{
    //                    hashmap.put(girl,new ArrayList<Integer>());
    //                    hashmap.get(girl).add(Integer.valueOf(boy));
    //                }
    //            }//初始化
    //
    //            for(Integer each:hashmap.keySet()){
    //                Integer[] temp = {};
    //                temp = hashmap.get(each).toArray(temp);
    //                combination[each] = temp;
    //            }
    //            int res = 0;
    //
    //
    //            sort_by_length(combination);//通过每一行长度进行冒泡排序
    //
    //            for(int i = 1;i<combination.length;++i){
    //                for(int j = 0;j<combination[i].length;++j){
    //                    if(boy_flag[combination[i][j]]==1){
    //                        res++;
    //                        boy_flag[combination[i][j]] = 0;
    //                    }
    //                }
    //            }
    //            System.out.println(res);
    //
    //        }
    //    }
    //
    //    private static void sort_by_length(Integer[][] arr){
    //        boolean flag = false;
    //        for(int i = 1;i<= arr.length;++i){
    //            for(int j = 2;j <= arr.length - i;++j){
    //                if(arr[j].length < arr[j-1].length){
    //                    Integer[] temp = arr[j];
    //                    arr[j] = arr[j-1];
    //                    arr[j-1] = temp;
    //                    flag = true;
    //                }
    //            }
    //            if(!flag){
    //                break;
    //            }
    //        }
    //    }
    }

    代码已经ac

    希望对大家有所帮助

    以上

  • 相关阅读:
    Annotation
    jdbc
    集合
    与运行环境交互
    计数排序and基数排序
    面向对象下
    面向对象
    流程控制与数组
    庆祝自己的BLOG开张
    Raspberry Pi配置为无线路由器
  • 原文地址:https://www.cnblogs.com/lavender-pansy/p/12381083.html
Copyright © 2020-2023  润新知