1. 程式人生 > 其它 >洛谷訓練場——簡單模擬 排座位(P1056)

洛谷訓練場——簡單模擬 排座位(P1056)

技術標籤:java演算法動態規劃資料結構貪心演算法

題目描述

上課的時候總會有一些同學和前後左右的人交頭接耳,這是令小學班主任十分頭疼的一件事情。不過,班主任小雪發現了一些有趣的現象,當同學們的座次確定下來之後,只有有限的D對同學上課時會交頭接耳。

同學們在教室中坐成了MN列,坐在第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;
}