首页 > 试题广场 >

排座椅

[编程题]排座椅
  • 热度指数:3290 时间限制:C/C++ 1秒,其他语言2秒 空间限制:C/C++ 50M,其他语言100M
  • 算法知识视频讲解
\hspace{15pt}教室内共有 nm 列座位,坐在第 i 行第 j 列同学的位置记为 (i,j)

\hspace{15pt}为了方便进出,班主任计划设置 k横向通道(贯穿整列的水平通道)与 l纵向通道(贯穿整行的竖直通道)。通道位于相邻两行(或两列)之间。

\hspace{15pt}班主任记录了 d 对经常交头接耳的同学,他们的位置 (x_i,y_i)(p_i,q_i) 保证相邻(上下或左右)。她希望通过合理放置通道,使尽可能多的"交头接耳"对被通道隔开。

\hspace{15pt}现请你输出唯一的最优方案,在该方案下,仍未被通道隔开的"交头接耳"对的数量最少。

输入描述:
\hspace{15pt}第一行输入五个整数 n,m,k,l,d\left(2\leqq n,m\leqq 10^3;\ 0<k<n;\ 0<l<m;\ 0< d \leqq 2\times\min\{n\times m,2\times10^3\}\right)

\hspace{15pt}接下来 d 行,每行输入四个整数 x_i,y_i,p_i,q_i,表示坐标 (x_i,y_i)(p_i,q_i) 的两位同学会交头接耳,且两坐标上下相邻或左右相邻。

\hspace{15pt}保证最优方案存在且唯一。


输出描述:
\hspace{15pt}第一行输出 k 个严格递增的整数 a_1,a_2,\dots,a_k\left(1\leqq a_1<\dots<a_k\leqq n-1\right),在行 a_ia_i+1 之间设置横向通道。

\hspace{15pt}第二行输出 l 个严格递增的整数 b_1,b_2,\dots,b_l\left(1\leqq b_1<\dots<b_l\leqq m-1\right),在列 b_ib_i+1 之间设置纵向通道。
示例1

输入

4 5 1 2 3
4 2 4 3
2 3 3 3
2 5 2 4

输出

2
2 4

说明

\hspace{15pt}该样例如下图所示,蓝底斜线方格为第一对交头接耳的同学,绿底带叉方格为第二对交头接耳的同学,粉底带星方格为第三对交头接耳的同学。粗线代表通道。该划分方案为唯一最优方案。

示例2

输入

2 2 1 1 4
1 1 1 2
1 1 2 1
2 1 2 2
1 2 2 2

输出

1
1
//排序和后续处理上有点麻烦。
import java.util.*;
import java.io.*;
import java.util.stream.Collectors;

//横向只能分割上下相邻,纵向只能分割左右相邻
//遍历相邻同学对,统计横向或纵向的某条线各能隔开多少同学。
//选择符合题意的最多横向和纵向同学
public class Main {
    public static void main(String[] args) throws IOException {
        BufferedReader bf = new BufferedReader(new InputStreamReader(System.in));
        int[] line1 = Arrays.stream(bf.readLine().split(" ")).mapToInt(
                          Integer::parseInt).toArray();
        //分别统计行和列的整数
        TreeMap<Integer, Integer> tr = new TreeMap<>();
        TreeMap<Integer, Integer> tc = new TreeMap<>();

        for (int i = 1; i <= line1[4]; i++) {
            String[] pair = bf.readLine().split(" ");
            if (pair[1].equals(pair[3])) {
                int row = Math.min(Integer.parseInt(pair[0]), Integer.parseInt(pair[2]));
                tr.put(row, tr.getOrDefault(row, 0) + 1);
            } else {
                int col = Math.min(Integer.parseInt(pair[1]), Integer.parseInt(pair[3]));
                tc.put(col, tc.getOrDefault(col, 0) + 1);
            }
        }
        StringJoiner sj = new StringJoiner(" ");
        Map<Integer, Integer> Desc1 = tr.entrySet().stream()
                                      .sorted(Map.Entry.<Integer, Integer>comparingByValue().reversed()) // 降序排序
                                      .collect(Collectors.toMap(
                                              Map.Entry::getKey,
                                              Map.Entry::getValue,
                                              (e1, e2) -> e1, // 处理键冲突(此处无冲突)
                                              LinkedHashMap::new // 保持排序后的顺序
                                               ));
        int i = 0, j = 0;
        //收集到sj中进行然后再次用比较器排序
        for (Map.Entry<Integer, Integer> entry : Desc1.entrySet()) {
            if (i < line1[2]) {
                sj.add(entry.getKey().toString());
            } else {
                break;
            }
            i++;
        }
        String[] res = sj.toString().split(" ");
        Arrays.sort(res,(a,b)->Integer.parseInt(a)-Integer.parseInt(b));
        System.out.println(String.join(" ", res));
        Map<Integer, Integer> Desc2 = tc.entrySet().stream()
                                      .sorted(Map.Entry.<Integer, Integer>comparingByValue().reversed()) // 降序排序
                                      .collect(Collectors.toMap(
                                              Map.Entry::getKey,
                                              Map.Entry::getValue,
                                              (e1, e2) -> e1, // 处理键冲突(此处无冲突)
                                              LinkedHashMap::new // 保持排序后的顺序
                                               ));
        sj = new StringJoiner(" ");
        for (Map.Entry<Integer, Integer> entry : Desc2.entrySet()) {
            if (j < line1[3]) {
                sj.add(entry.getKey().toString());
            } else {
                break;
            }
            j++;
        }
        res = sj.toString().split(" ");
        Arrays.sort(res,(a,b)->Integer.parseInt(a)-Integer.parseInt(b));
        System.out.println(String.join(" ", res));
    }
}

发表于 2025-09-08 17:44:04 回复(0)
import java.util.*;

public class Main {
    public static void main(String[] args) {
        Scanner sc = new Scanner(System.in);
        int n = sc.nextInt(); // 行数
        int m = sc.nextInt(); // 列数
        int k = sc.nextInt(); // 横向通道数量
        int l = sc.nextInt(); // 纵向通道数量
        int d = sc.nextInt(); // 交头接耳的对数

        // 统计每个横向通道能隔开的对数
        int[] horizontal = new int[n];
        // 统计每个纵向通道能隔开的对数
        int[] vertical = new int[m];

        for (int i = 0; i < d; i++) {
            int x1 = sc.nextInt();
            int y1 = sc.nextInt();
            int x2 = sc.nextInt();
            int y2 = sc.nextInt();

            if (x1 == x2) {
                // 左右相邻,属于纵向通道
                int col = Math.min(y1, y2);
                vertical[col]++;
            } else {
                // 上下相邻,属于横向通道
                int row = Math.min(x1, x2);
                horizontal[row]++;
            }
        }

        // 选择最优的横向通道
        List<Integer> hList = new ArrayList<>();
        for (int i = 1; i < n; i++) {
            hList.add(i);
        }
        // 按重要性降序排序,重要性相同则按位置升序
        Collections.sort(hList, (a, b) -> {
            if (horizontal[a] != horizontal[b]) {
                return Integer.compare(horizontal[b], horizontal[a]);
            } else {
                return Integer.compare(a, b);
            }
        });
        // 取前k个并排序
        List<Integer> hResult = hList.subList(0, k);
        Collections.sort(hResult);

        // 选择最优的纵向通道
        List<Integer> vList = new ArrayList<>();
        for (int i = 1; i < m; i++) {
            vList.add(i);
        }
        // 按重要性降序排序,重要性相同则按位置升序
        Collections.sort(vList, (a, b) -> {
            if (vertical[a] != vertical[b]) {
                return Integer.compare(vertical[b], vertical[a]);
            } else {
                return Integer.compare(a, b);
            }
        });
        // 取前l个并排序
        List<Integer> vResult = vList.subList(0, l);
        Collections.sort(vResult);

        // 输出横向通道
        for (int i = 0; i < hResult.size(); i++) {
            if (i > 0) {
                System.out.print(" ");
            }
            System.out.print(hResult.get(i));
        }
        System.out.println();

        // 输出纵向通道
        for (int i = 0; i < vResult.size(); i++) {
            if (i > 0) {
                System.out.print(" ");
            }
            System.out.print(vResult.get(i));
        }
        System.out.println();
    }
}

发表于 2025-09-03 21:18:30 回复(0)