OJ-0802

题目

在这里插入图片描述
在这里插入图片描述
示例1:

input:
8 9 7 5 6 3 2 1 4
7 8 9 4 2 1 3 5 6
output:
0

示例2:

input:
7 9 8 5 6 4 2 1 3
7 8 9 4 2 1 3 5 6
output:
1

示例3:

input:
7 9 8 5 6 4 2 1 3
7 5 4 9 8 6 2 1 3
output:
2

7 6 9 8 5 4 2 1 3
6 9 8 5 7 4 2 1 3
示例4:

input:
7 9 8 5 6 4 2 1 3
7 5 2 9 6 1 8 4 3
output:
4

7 5 9 8 6 4 2 1 3
7 5 2 9 6 1 8 4 3
__
7 5 2 9 8 6 4 1 3
7 5 2 9 6 1 8 4 3
__
7 5 2 1 9 8 6 4 3
7 5 2 9 6 1 8 4 3
__
7 5 2 6 1 9 8 4 3
7 5 2 9 6 1 8 4 3

示例5:

input:
15 16 14 12 11 13 7 9 8 5 6 4 2 1 3
14 12 11 13 15 16 7 5 2 9 6 1 8 4 3
output:
5

分析

要点:在排队的基础上移动学生位置,实现要求的分组,分组的顺序不做要求,求移动学生次数的最小值。

题解

优化:

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Scanner;

public class 学生重新排队 {
    public static List<Integer> cur_order = new ArrayList<>();
    public static List<Integer> final_order = new ArrayList<>();
    public static List<Integer> order_flags = new ArrayList<>(); // 分组成功标识
    public static int n = 0;
    public static Map<Integer, Integer> relations = new HashMap<>(); // map<学生编号, 组号>
    public static int result = 0;

    public static void main(String[] args) {
        Scanner in = new Scanner(System.in);
        String[] tmp1 = in.nextLine().split(" ");
        for (String s : tmp1) {
            cur_order.add(Integer.parseInt(s));
        }
        String[] tmp2 = in.nextLine().split(" ");
        for (String s : tmp2) {
            final_order.add(Integer.parseInt(s));
        }
        n = cur_order.size();
        for (int j = 0; j < n / 3; j++) {
            order_flags.add(0);
        }
        for (int i = 0; i < n; i++) {
            relations.put(final_order.get(i), i / 3);
        }

        while (!check_order()) {
            for (int i = 0; i < n; i++) {
                int group = relations.get(cur_order.get(i));
                if (order_flags.get(group) == 0) {
                    if (get_cur_order_cnt(i) == 1) {
                        result += 1;
                        order_flags.set(group, 1);
                        for (int j = 0; j < n; j++) {
                            if (j != i && j != i + 1) {
                                move(j, i);
                            }
                        }
                    }
                    if (get_cur_order_cnt(i) == 0) { // 操作2次情况
                        result += 2;
                        order_flags.set(group, 1);
                        for (int j = 0; j < n; j++) {
                            if (j != i) {
                                move(j, i);
                            }
                        }
                    }
                }
            }
        }
        System.out.println(result);
    }

    // 判断每一位同学是否都在对应组内
    public static boolean check_order() {
        for (int i = 0; i < n; i += 3) {
            int group = relations.get(cur_order.get(i));
            if (group != relations.get(cur_order.get(i + 1)) || group != relations.get(cur_order.get(i + 2))) {
                return false;
            }
        }
        return true;
    }

    public static void move(int remove_index, int append_index) {
        if (relations.get(cur_order.get(remove_index)).equals(relations.get(cur_order.get(append_index)))) {
            int remove_element = cur_order.remove(remove_index);
            cur_order.add(append_index, remove_element);
        }
    }

    /**
     * 以当前学生为准,判断他后面的两个学生是否与其同组
     *
     * @param index 索引
     * @return 0:当前学生后面0个学生与其同组,需操作2次;1:当前学生后面1个学生与其同组,需操作1次;2:当前学生后面2个学生与其同组,无需操作
     */
    public static int get_cur_order_cnt(int index) {
        int group = relations.get(cur_order.get(index));
        int count = 0;
        if (index + 1 < n && relations.get(cur_order.get(index + 1)) == group) {
            count += 1;
            if (index + 2 < n && relations.get(cur_order.get(index + 2)) == group) {
                order_flags.set(group, 1);
                count += 1;
            }
        }
        return count;
    }
}
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Scanner;

public class Main {
    public static List<Integer> cur_order = new ArrayList<>();
    public static List<Integer> final_order = new ArrayList<>();
    public static List<Integer> order_flags = new ArrayList<>();
    public static int n = 0;
    public static Map<Integer, Integer> relations = new HashMap<>(); // map<学生编号, 组号>
    public static int result = 0;

    public static void main(String[] args) {
        Scanner in = new Scanner(System.in);
        String[] tmp1 = in.nextLine().split(" ");
        for (String s : tmp1) {
            cur_order.add(Integer.parseInt(s));
        }
        String[] tmp2 = in.nextLine().split(" ");
        for (String s : tmp2) {
            final_order.add(Integer.parseInt(s));
        }
        n = cur_order.size();
        for (int j = 0; j < n / 3; j++) {
            order_flags.add(0);
        }
        for (int i = 0; i < n; i++) {
            relations.put(final_order.get(i), i / 3);
        }

        while (!check_order()) {
            boolean operation_flag = false;
            for (int i = 0; i < n; i++) {
                int group = relations.get(cur_order.get(i));
                if (order_flags.get(group) == 0) {
                    if (get_cur_order_cnt(i, group) == 1) {
                        result += 1;
                        operation_flag = true;
                        for (int j = 0; j < n; j++) {
                            if (j != i && j != i + 1) {
                                move(j, i);
                            }
                        }
                    }
                }
            }
            if (!operation_flag) {
                two_step_move();
            }
        }
        System.out.println(result);
    }

    // 判断每一位同学是否都在对应组内
    public static boolean check_order() {
        for (int i = 0; i < n; i += 3) {
            int group = relations.get(cur_order.get(i));
            if (group != relations.get(cur_order.get(i + 1)) && group != relations.get(cur_order.get(i + 2))) {
                return false;
            }
        }
        return true;
    }

    public static void move(int remove_index, int append_index) {
        if (relations.get(cur_order.get(remove_index)).equals(relations.get(cur_order.get(append_index)))) {
            int remove_element = cur_order.get(remove_index);
            cur_order.remove(remove_index);
            cur_order.add(append_index, remove_element);
        }
    }

    public static void two_step_move() {
        for (int i = 0; i < n; i = i + 3) {
            int group = relations.get(cur_order.get(i));
            if (group != relations.get(cur_order.get(i + 1)) && group != relations.get(cur_order.get(i + 2))) {
                continue;
            }
            if (order_flags.get(group) == 0) {
                result += 2;
                for (int j = 0; j < n; j++) {
                    if (!cur_order.get(j).equals(cur_order.get(i))) {
                        move(j, i);
                    }
                }
            }
        }
    }

    public static int get_cur_order_cnt(int index, int group) {
        int count = 0;
        if (index + 1 < n && relations.get(cur_order.get(index + 1)) == group) {
            order_flags.set(group, 1);
            count += 1;
            if (index + 2 < n && relations.get(cur_order.get(index + 2)) == group) {
                count += 1;
            }
        }
        return count;
    }
}

参考

解题思路:
1.建立索引字典:将学生目前排队情况转换成索引字典,其中键为学生编号,值为该学生在队伍中的索引位置。
2.遍历每个小组:对于每个小组,遍历其中的学生。
3.计算目标位置:对于每个小组的学生,计算其目标位置。
目标位置是该学生在小组中的相对位置乘以3再加上该小组在整个队伍中的位置。
4,调整位置:如果当前位置不是目标位置,则需要进行调整。
通过交换当前位置和目标位置的学生,使得小组内的学生在队伍中是连续排列。
5,更新索引字典:调整后更新索引字典,确保索引字典中的信息是最新的。
6.累计调整次数:统计每次调整,最终得到最少调整次数。

通过以上步骤,可以确保同组成员在队伍中是彼此相连的。在代码中,需要注意索引的计算以及列表中的元素交换。这个思路的关键在于通过交换操作,逐步调整队伍中学生的位置,使得每个小组的学生都连续排列。

import java.util.Scanner;
import java.util.*;
import java.util.stream.Stream;
import java.util.HashMap;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import java.util.stream.Collectors;
 
public class Main {
    public static List<Integer> cur_order = new ArrayList<>();
    public static List<Integer> final_order= new ArrayList<>();
    public static List<Integer> order_flags= new ArrayList<>();
    public static int n=0;
    //map<学生编号, 组号>
    public static Map<Integer, Integer> relations=new HashMap<>(); 
    public static int result = 0;
    
    //判断每一位同学是否都在对应组内
    public static boolean check_order(){
        for (int i = 0; i < cur_order.size(); i += 3) {
            if (!(relations.get(cur_order.get(i)) == relations.get(cur_order.get(i + 1)) && 
                relations.get(cur_order.get(i)) == relations.get(cur_order.get(i + 2)))){
                return false;
            }
        }
        return true;
    }
    
    public static void move(int cur_student, int remove_index, int append_index){
        if (relations.get(cur_order.get(remove_index)) == relations.get(cur_student)) {
            int remove_element = cur_order.get(remove_index);
            cur_order.remove(remove_index);
            cur_order.add(append_index, remove_element);
        }
    }
    
    public static void two_step_move(){
        for (int i = 0; i < n; i++) {
            int cur_student = cur_order.get(i);
            if (order_flags.get(relations.get(cur_student))==0) {
                result += 2;
                for (int j = 0; j < n; j++) {
                    if (cur_order.get(j) != cur_student) {
                        move(cur_student,j,i);
                    }
                }
            }
        }
    }
    
    //以当前学生为准,判断他后面的两个学生是否与其同组
    public static int get_cur_order_cnt(int index, int cur_student){
        int count = 0; 
        int cur_stu_order = relations.get(cur_student);
        if (index + 1 < n && relations.get(cur_order.get(index + 1)) == cur_stu_order) {
            order_flags.set(relations.get(cur_student), 1);
            count+=1;
            if(index + 2 < n && relations.get(cur_order.get(index + 2)) == cur_stu_order){
                count+=1;
            }
        }
        return count;
    }
 
    public static void main(String[] args) {
        Scanner in = new Scanner(System.in);
        String[] tmp1 = in.nextLine().split(" ");
        for (int i = 0; i < tmp1.length; i++) {  
            cur_order.add(Integer.parseInt(tmp1[i]));
        }
        String[] tmp2 = in.nextLine().split(" ");
        for (int i = 0; i < tmp2.length; i++) {  
            final_order.add(Integer.parseInt(tmp2[i]));
        }
        n = cur_order.size();
        for (int j = 0; j < n; j++) {
            order_flags.add(0);
        }
        
        int k=0;
        while(true){
            if(k>=n){
                break;
            } else {
                for (int j = 0; j < 3; j++) {
                    relations.put((final_order.get(k + j)) , k / 3 + 1);
                }
            }
            k+=3;
        }
    
     
        while (!check_order()) {
            int operation_flag = 0;  
    
            int i=0;
            while(true){
                if(i>=n){
                    break;
                } else {
                    int cur_student = cur_order.get(i);
                    if (order_flags.get(relations.get(cur_student))==0){
                        //后面有一个学生与其同组,那么需要操作1次
                        //后面有两个学生与其同组,那么需要操作0次,无需操作
                        if (get_cur_order_cnt(i, relations.get(cur_student)) == 1) {
                            result += 1;
                            operation_flag = 1; 
                            for (int j = 0; j < n; j++) {
                                if (j != i && j != i + 1) {
                                    move(cur_student,j,i);
                                }
                            }
                        }
                    } 
     
                }
                i+=1;
            }
    
            // 若每一个学生后面两个学生都没有与其同组的情况
            // 需要操作2次,将其后面两位都移动,然后再循环的去遍历,判读是否满足分组情况
            if (operation_flag==0) {
                two_step_move();
            }
        }
        System.out.println(result);
    }
 
    public static int[] split(String input_str){
        String[] tmp2 = input_str.split(",");
        int[] nums = new int[tmp2.length];
        for (int i = 0; i < tmp2.length; i++) {  
            nums[i] = Integer.parseInt(tmp2[i]);
        }
        return nums;
    }
}

https://blog.csdn.net/weixin_52908342/article/details/136288646

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值