洛谷訓練場——簡單模擬 排座位(P1056)
阿新 • • 發佈:2021-02-06
題目描述
上課的時候總會有一些同學和前後左右的人交頭接耳,這是令小學班主任十分頭疼的一件事情。不過,班主任小雪發現了一些有趣的現象,當同學們的座次確定下來之後,只有有限的D對同學上課時會交頭接耳。
同學們在教室中坐成了M行N列,坐在第i行第j列的同學的位置是(i,j),為了方便同學們進出,在教室中設定了K條橫向的通道,L條縱向的通道。
於是,聰明的小雪想到了一個辦法,或許可以減少上課時學生交頭接耳的問題:她打算重新擺放桌椅,改變同學們桌椅間通道的位置,因為如果一條通道隔開了2個會交頭接耳的同學,那麼他們就不會交頭接耳了。
請你幫忙給小雪編寫一個程式,給出最好的通道劃分方案。在該方案下,上課時交頭接耳的學生的對數最少
輸入樣例 輸出樣例
4 5 1 2 3 2
4 2 4 3 2 4
2 3 3 3
2 5 2 4
樣例最優解圖析:
題目分析:
既然是模擬題,先看情景需求,再看樣例,一看到“最好的”、“最優解” ,不禁感嘆,又是一道貪心,再通過對樣例圖的分析可以知道,每一行每一列都有一個價值,根據每一行的價值從大到小,進行優先切分,
然後再根據列的價值對列進行切分。貪心演算法中價值決定資料處理的優先順序
實現思路:
題目的意思很明確想讓我們用有限的橫、縱線將最多的交頭接耳的學生分開,題目說一定相鄰,那麼交頭接耳的人要麼y相等,要麼x相等,由於,線有橫縱兩種,所以下,x、y分別考慮。那麼如何得到每一列x,y的價值呢
我最開始的想法是結構體記錄下兩個數的位置,但後來一像既然是相鄰的那麼只需要記錄一個座標的x或y即可,所以我選擇了用陣列直接儲存。當x相等的時候儲存下y的頻數,在x不等的時候存下x的頻數。完成記錄後,對x,y的頻數
進行桶排序,再將排序結果的索引存到新的陣列,這時權重的排序就完畢了,然後只要新陣列不為0的數從 0 到 k或l就是需要切割的行列。
題解:
#include <stdio.h> #include <stdlib.h> int min(int a, int b); int main() { int m = 0, n = 0, k = 0, l = 0, d = 0; int x[1010] = {0}, y[1010] = {0}; int col[1010] = {0}, row[1010] = {0}; scanf("%d%d%d%d%d", &m, &n, &k, &l, &d); for (int i = 1; i <= d; i++) { int x1, y1, x2, y2; scanf("%d%d%d%d", &x1, &y1, &x2, &y2); if (x1 != x2) //判斷x是否相等 { //不等時一定存在y有相同 //取最小加一最大減一 y[min(x1, x2)]++; //價值 } else { //等於 x[min(y1, y2)]++; } } for (int i = 1; i <= k; i++) { //對y進行價值排序 int max = -1; int index = 0; for (int j = 1; j < m; j++) { if (y[j] > max) { max = y[j]; index = j; } } y[index] = 0; col[index]++; } for (int i = 1; i <= l; i++) {//對y進行價值排序 int max = -1; int index = 0; for (int j = 1; j < n; j++) { if (x[j] > max) { max = x[j]; index = j; } } x[index] = 0; row[index]++; } for (int i = 0; i < 1010; i++) { if (col[i])//遍歷x { printf("%d ", i); } } printf("\n"); for (int i = 0; i< 1010;i++) { if (row[i]) { printf("%d ", i); } } return 0; } int min(int a, int b) { return a < b ? a : b; }