【NOIP普及】排座椅
阿新 • • 發佈:2021-07-21
【NOIP普及】排座椅
題目描述
上課的時候總會有一些同學和前後左右的人交頭接耳,這是令小學班主任十分頭疼的一件事情。不過,班主任小雪發現了一些有趣的現象,當同學們的座次確定下來之後,只有有限的 D 對同學上課時會交頭接耳。
同學們在教室中坐成了 M 行 N 列,坐在第 ii 行第 jj 列的同學的位置是(i,j),為了方便同學們進出,在教室中設定了KK 條橫向的通道,L 條縱向的通道。
於是,聰明的小雪想到了一個辦法,或許可以減少上課時學生交頭接耳的問題:她打算重新擺放桌椅,改變同學們桌椅間通道的位置,因為如果一條通道隔開了 2 個會交頭接耳的同學,那麼他們就不會交頭接耳了。
請你幫忙給小雪編寫一個程式,給出最好的通道劃分方案。在該方案下,上課時交頭接耳的學生的對數最少。
輸入格式
第一行,有 5 個用空格隔開的整數,分別是M,N,K,L,D(2<=M,N<=1000,0<=K<M,0<=L<N,D<=2000)
接下來的D行,每行有 4個用空格隔開的整數。第 i行的 4 個整數$X_i,Y_i,P_i,Q_i$,表示坐在$(X_i,Y_i)與(P_i,Q_i)$的兩個同學會交頭接耳(輸入保證他們前後相鄰或者左右相鄰)。
輸入資料保證最優方案的唯一性。
輸出格式
樣例輸入
4 5 1 2 3
4 2 4 3
2 3 3 3
2 5 2 4
樣例輸出
2
2 4
解題思路
這道題就是讓我們求在哪裡劃線可以隔開最多的兩個值相等的數。
我們可以用貪心演算法。
首先,查詢每相鄰兩行有幾對會交頭接耳的,只要有,就用一個結構體儲存下數量和當前所在的行。統計完後,按照數量從大到小排序。然後取出前k個數,再按照行的編號從小到大排序,輸出即可。
Code
#include<algorithm> #include<iostream> #include<cstdio> #define sco 2000 using namespace std; struct td{ int number,hen; }class2[sco],class1[sco]; int m,n,k,l,d,a[sco],b[sco]; bool cmp(td x1,td y1){ return x1.number>y1.number; } int main(){ freopen("seat.in","r",stdin); freopen("seat.out","w",stdout); scanf("%d%d%d%d%d",&m,&n,&k,&l,&d); for(int i=1;i<=n;++i)class1[i].hen=i; for(int i=1;i<=m;++i)class2[i].hen=i; for(int i=1;i<=d;++i){ int x1,y1,x2,y2; scanf("%d%d%d%d",&x1,&y1,&x2,&y2); if(x1==x2 and y1+1==y2){ ++class1[y1].number; } else if(x1==x2 and y2+1==y1){ ++class1[y2].number; } else if(x1+1==x2 and y1==y2){ ++class2[x1].number; } else if(x2+1==x1 and y1==y2){ ++class2[x2].number; } } sort(class1+1,class1+n+1,cmp); sort(class2+1,class2+1+m,cmp); for(int i=1;i<=k;++i){ a[i]=class2[i].hen; }sort(a+1,a+1+k); for(int i=1;i<=k;++i){ printf("%d ",a[i]); } if(k)printf("\n"); for(int i=1;i<=l;++i){ a[i]=class1[i].hen; }sort(a+1,a+l+1); for(int i=1;i<=l;++i){ printf("%d ",a[i]); } return 0; fclose(stdin); fclose(stdout); }
謝謝閱讀
本文來自部落格園,作者:基德不基,轉載請註明原文連結:https://www.cnblogs.com/ssllyw/p/15038194.html