【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;
}

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章