IMA+DeepSeekR1+本地知识库撰写NOIP2008普及组T2【排座椅】题解

目录

一、提问词

二、DeepSeekR1回复

题目描述

解题思路

实现代码

 代码说明

三、说明


【IMA+DeepSeekR1+本地知识库】撰写NOIP2008普及组复赛题解系列

1、IMA+DeepSeekR1+本地知识库撰写NOIP2008普及组T1【ISBN 号码】题解-CSDN博客

2、IMA+DeepSeekR1+本地知识库撰写NOIP2008普及组T2【排座椅】题解-CSDN博客

3、IMA+DeepSeekR1+本地知识库撰写NOIP2008普及组T3【传球游戏】题解-CSDN博客

4、【IMA+DeepSeekR1+本地文件】撰写NOIP2008普及组T4【立体图】题解-CSDN博客

一、提问词

请撰写NOIP2008普及组T2【排座椅】题解,要求:  
一、从文件“seat.in”读数据,答案写入文件“seat.out”。  
二、题解至少包括以下几个部分:  
1、题目描述  
2、解题思路及推理过程  
3、实现代码  
4、代码说明

二、DeepSeekR1回复

题目描述

教室中有 M 行 N 列座位。有 D 对同学上课会交头接耳,现需设置 K 条横向通道(分隔相邻行)和 L 条纵向通道(分隔相邻列),使得被分隔的吵闹同学对数最多。要求输出通道位置,且按编号升序排列。 4

输入
从文件 seat.in 读取:
第一行为 M, N, K, L, D,接下来 D 行描述吵闹同学对的位置 (x1,y1) 和 (x2,y2)

输出
写入文件 seat.out
第一行为选中的 K 个横向通道的行编号(升序),第二行为 L 个纵向通道的列编号(升序)。


解题思路
  1. 贪心策略
    • 统计每行(row[i])和每列(col[j])分隔后能减少的吵闹对数。
    • 优先选择分隔有效对数最多的行和列。
  2. 排序规则
    • 按吵闹对数的降序排序,若相同则按编号升序排序。
  3. 输出处理
    • 对最终选中的行、列分别排序,确保输出升序。

实现代码
#include <bits/stdc++.h>
using namespace std;

const int MAXN = 1010;

struct Node {
    int id, cnt;
    Node(int _id = 0) : id(_id), cnt(0) {}
};

bool cmp(const Node &a, const Node &b) {
    return a.cnt > b.cnt || (a.cnt == b.cnt && a.id < b.id);
}

int main() {
    freopen("seat.in", "r", stdin);
    freopen("seat.out", "w", stdout);
    
    int M, N, K, L, D;
    cin >> M >> N >> K >> L >> D;

    Node row[MAXN], col[MAXN];
    for (int i = 1; i < M; i++) row[i] = Node(i);
    for (int i = 1; i < N; i++) col[i] = Node(i);

    while (D--) {
        int x1, y1, x2, y2;
        cin >> x1 >> y1 >> x2 >> y2;
        if (y1 == y2) row[min(x1, x2)].cnt++;  // 同一列,分隔行
        if (x1 == x2) col[min(y1, y2)].cnt++;  // 同一行,分隔列
    }

    sort(row + 1, row + M, cmp);
    sort(col + 1, col + N, cmp);

    vector<int> ans_r, ans_c;
    for (int i = 1; i <= K; i++) ans_r.push_back(row[i].id);
    for (int i = 1; i <= L; i++) ans_c.push_back(col[i].id);

    sort(ans_r.begin(), ans_r.end());
    sort(ans_c.begin(), ans_c.end());

    for (int i = 0; i < ans_r.size(); i++) 
        cout << ans_r[i] << (i == ans_r.size()-1 ? "\n" : " ");
    for (int i = 0; i < ans_c.size(); i++)
        cout << ans_c[i] << (i == ans_c.size()-1 ? "\n" : " ");
    
    return 0;
}
 代码说明
  1. 数据结构
    • Node 结构体保存行/列的编号和吵闹对数。
  2. 核心逻辑
    • 输入处理:统计每行、每列的分隔有效次数。
    • 排序选择:贪心选择有效次数最多的行和列,若次数相同按编号升序。
  3. 输出保证
    • 最终结果的升序排序确保题目格式要求。
  4. 复杂度
    • 时间复杂度为 O(M log M + N log N),能够处理题目最大数据规模。

示例输入输出匹配

  • 输入数据保证唯一最优解,代码通过贪心和排序正确捕捉最优分隔方案。

三、说明

1、上述题解中的参考代码,经【Cena】评测结论为AC。