【luogu/贪心】排座椅(求出现频率前k个的元素)

题目描述

上课的时候总会有一些同学和前后左右的人交头接耳,这是令小学班主任十分头疼的一件事情。不过,班主任小雪发现了一些有趣的现象,当同学们的座次确定下来之后,只有有限的D对同学上课时会交头接耳。

同学们在教室中坐成了MMM行NNN列,坐在第i行第j列的同学的位置是(i,j)(i,j)(i,j),为了方便同学们进出,在教室中设置了KKK条横向的通道,LLL条纵向的通道。

于是,聪明的小雪想到了一个办法,或许可以减少上课时学生交头接耳的问题:她打算重新摆放桌椅,改变同学们桌椅间通道的位置,因为如果一条通道隔开了222个会交头接耳的同学,那么他们就不会交头接耳了。

请你帮忙给小雪编写一个程序,给出最好的通道划分方案。在该方案下,上课时交头接耳的学生的对数最少。

输入格式

第一行,有555个用空格隔开的整数,分别是M,N,K,L,D(2≤N,M≤1000,0≤K<M,0≤L<N,D≤2000)M,N,K,L,D(2 \le N,M \le 1000,0 \le K<M,0 \le L<N,D \le 2000)M,N,K,L,D(2≤N,M≤1000,0≤K<M,0≤L<N,D≤2000)

接下来的DDD行,每行有444个用空格隔开的整数。第iii行的444个整数Xi,Yi,Pi,QiX_i,Y_i,P_i,Q_iXi​,Yi​,Pi​,Qi​,表示坐在位置(Xi,Yi)(X_i,Y_i)(Xi​,Yi​)与(Pi,Qi)(P_i,Q_i)(Pi​,Qi​)的两个同学会交头接耳(输入保证他们前后相邻或者左右相邻)。

输入数据保证最优方案的唯一性。

输出格式

共两行。
第一行包含KKK个整数a1,a2,…,aKa_1,a_2,…,a_Ka1​,a2​,…,aK​,表示第a1a_1a1​行和a1+1a_1+1a1​+1行之间、第a2a_2a2​行和a2+1a_2+1a2​+1行之间、…、第aKa_KaK​行和第aK+1a_K+1aK​+1行之间要开辟通道,其中ai<ai+1a_i< a_i+1ai​<ai​+1,每两个整数之间用空格隔开(行尾没有空格)。

第二行包含LLL个整数b1,b2,…,bLb_1,b_2,…,b_Lb1​,b2​,…,bL​,表示第b1b_1b1​列和b1+1b_1+1b1​+1列之间、第b2b_2b2​列和b2+1b_2+1b2​+1列之间、…、第bLb_LbL​列和第bL+1b_L+1bL​+1列之间要开辟通道,其中bi<bi+1b_i< b_i+1bi​<bi​+1,每两个整数之间用空格隔开(列尾没有空格)。

输入输出样例

输入 #1

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

输出 #1

2
2 4

基本思路:

又是最优解问题啊,这里很显然采用的是贪心的算法

问题的本质在于求解求解出现频率为前k个元素

这里有两类做法,我稍微提一下:

  1.  使用unordered_map存储出现频率,用priority_queue讲遍历的元素存进来(注意利用pair的字典序),对元素的输出顺序也有要求可以再考虑加一个vector或者priority_queue。
  2.  使用计数排序。每次找到一个最大值就把相应桶的值清零。这样循环做k次就可以得到前k个最大的元素。至于最后的顺序输出可以再次利用桶的思想。

AC代码:

(只提供法1的版本,法2的自行看luogu题解)

#include<bits/stdc++.h>
using namespace std;

int main() {
   int m, n;
   int k, l;
   int d;
   cin >> m >> n >> k >> l >> d;
   
   unordered_map<int ,int> row_map, col_map;
    for (int i = 0; i < d; ++i) {
      int x1, y1, x2, y2;
      cin >> x1 >> y1 >> x2 >> y2;
      if (x1 == x2) {
        int y = (y1 < y2)? y1 : y2;
        ++col_map[y];
      }
      if (y1 == y2) {
        int x = (x1 < x2)? x1 : x2;
        ++row_map[x];
      }
    }

    // 由于pair<int, int>大小是按照字典序来的
    // 所以我这里采用 first记录出现次数, second记录单词
    priority_queue<pair<int, int>> row, col;
    for (auto i = row_map.begin(); i != row_map.end(); ++i) {
      row.emplace(i->second, i->first);
    }
    for (auto i = col_map.begin(); i != col_map.end(); ++i) {
      col.emplace(i->second, i->first);
    }

    // 按照次序打印
    priority_queue<int, vector<int>, greater<int>> r, c;
    for (int i = 1; i <= k; ++i) {
      r.push(row.top().second);
      row.pop();
    }
    for (int i = 1; i <= k; ++i) {
      cout << r.top() << " ";
      r.pop();
    }
    cout << endl;
    for (int i = 1; i <= l; ++i) {
      c.push(col.top().second);
      col.pop();
    }
    for (int i = 1; i <= l; ++i) {
      cout << c.top() << " ";
      c.pop();
    }
    cout << endl;
    return 0;
}
发布了137 篇原创文章 · 获赞 19 · 访问量 1万+

猜你喜欢

转载自blog.csdn.net/qq_43338695/article/details/102881601