1. 程式人生 > >NOIP2008普及組 排座椅(貪心)

NOIP2008普及組 排座椅(貪心)

【問題描述】

  上課的時候總有一些同學和前後左右的人交頭接耳,這是令小學班主任十分頭疼的一件事情。不過,班主任小雪發現了一些有趣的現象,當同學們的座次確定下來之後,只有有限的D對同學上課時會交頭接耳。同學們在教室中坐成了M行N列,坐在第i行第j列的同學的位置是(i,j),為了方便同學們進出,在教室中設定了K條橫向的通道,L條縱向的通道。於是,聰明的小雪想到了一個辦法,或許可以減少上課時學生交頭接耳的問題:她打算重新擺放桌椅,改變同學們桌椅間通道的位置,因為如果一條通道隔開了兩個會交頭接耳的同學,那麼他們就不會交頭接耳了。

  請你幫忙給小雪編寫一個程式,給出最好的通道劃分方案。在該方案下,上課時交頭接耳的學生對數最少。

【輸入格式】

  第一行,有5各用空格隔開的整數,分別是M,N,K,L,D(2<=N,M<=1000,0<=K < M,0<=L< N,D<=2000)。
  下來D行,每行有4個用空格隔開的整數,第i行的4個整數Xi,Yi,Pi,Qi,表示坐在位置(Xi,Yi)與(Pi,Qi)的兩個同學會交頭接耳(輸入保證他們前後相鄰或者左右相鄰)。
  輸入資料保證最優方案的唯一性。

【輸出格式】

  第一行包含K個整數,a[1] a[2] … a[K],表示第a[1]行和a[1+1]行之間、第a[2]行和第a[2+1]行之間、…、第a[K]行和第a[K+1]行之間要開闢通道,其中a[i]< a[i+1],每兩個整數之間用空格隔開(行尾沒有空格)。
  第二行包含L個整數,b[1] b[2] … b[k],表示第b[1]列和b[1+1]列之間、第b[2]列和第b[2+1]列之間、…、第b[L]列和第b[L+1]列之間要開闢通道,其中b[i]< b[i+1],每兩個整數之間用空格隔開(行尾沒有空格)。

【輸入樣例】

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

【輸出樣例】

2
2 4

【樣例解釋】

     
  上圖中用符號*、※、+ 標出了3對會交頭接耳的學生的位置,圖中3條粗線的位置表示通道,圖示的通道劃分方案是唯一的最佳方案。

計算每一排和每一列的講話對數,貪心優先隔離講話對數多的排/列。記得最後要把答案由編號從小到大排序,否則釀成大禍。(血與淚的教訓)

#include<stdio.h>
#include<string.h>
#include<vector>
#include<algorithm>
using namespace std; const int maxn = 2502; int m, n, k, l, d; //計算每一排和每一列的講話對數,貪心優先隔離講話對數多的排/列 struct data { int w, id; }; data totx[maxn], toty[maxn]; //totx橫向講話 ,toty縱向講話 bool cmp(data a, data b) { if (a.w == b.w) return a.id<b.id; return a.w>b.w; } vector<int>x, y; int main() { //freopen("1.txt", "r", stdin); //freopen("seat.out", "w", stdout); scanf("%d%d%d%d%d", &m, &n, &k, &l, &d); memset(totx, 0, sizeof(totx)); memset(toty, 0, sizeof(toty)); for (int i = 1; i <= d; i++) { int x1, y1, p1, q1; scanf("%d %d %d %d", &x1, &y1, &p1, &q1); if (x1 == p1) //縱向講話 { if (y1>q1) toty[q1].w++, toty[q1].id = q1; else toty[y1].w++, toty[y1].id = y1; } if (q1 == y1) //橫向講話 { if (x1>p1) totx[p1].w++, totx[p1].id = p1; else totx[x1].w++, totx[x1].id = x1; } } sort(totx + 1, totx + m + 1, cmp); for (int i = 1; i <= k; i++) //橫向講話隔離 { x.push_back(totx[i].id); } sort(toty + 1, toty + n + 1, cmp); for (int i = 1; i <= l; i++) //縱向講話隔離 { y.push_back(toty[i].id); } sort(x.begin(), x.end()); sort(y.begin(), y.end()); for (int i = 0; i < k; i++) { printf("%d ", x[i]); } printf("\n"); for (int i = 0; i < l; i++) { printf("%d ", y[i]); } return 0; }