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

Posted 醉生梦死_0423

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了杭电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

希望对大家有所帮助

以上

 

以上是关于杭电oj_2063——过山车(java实现)的主要内容,如果未能解决你的问题,请参考以下文章

杭电oj_2035——人见人爱A^B(java实现)

杭电oj_2047——阿牛的EOF牛肉串(java实现)

hdu 2063 过山车(模板)

HDU——2063 过山车

hdu 2063 过山车

杭电oj2037——今年暑假不AC(java实现)