【08NOIP普及组】排座椅

http://ybt.ssoier.cn:8088/problem_show.php?pid=1943
【题目描述】
上课的时候总有一些同学和前后左右的人交头接耳,这是令小学班主任十分头疼的一件事情。不过,班主任小雪发现了一些有趣的现象,当同学们的座次确定下来之后,只有有限的D对同学上课时会交头接耳。同学们在教室中坐成了M行N列,坐在第ii行第jj列的同学的位置是(i,j),为了方便同学们进出,在教室中设置了K条横向的通道,L条纵向的通道。于是,聪明的小雪想到了一个办法,或许可以减少上课时学生交头接耳的问题:她打算重新摆放桌椅,改变同学们桌椅间通道的位置,因为如果一条通道隔开了两个会交头接耳的同学,那么他们就不会交头接耳了。

请你帮忙给小雪编写一个程序,给出最好的通道划分方案。在该方案下,上课时交头接耳的学生的对数最少。

【输入】
第一行,有55个用空格隔开的证书,分别是M,N,K,L,D(2≤N,M≤1000,0≤K<M,0≤L<N,D≤2000)M,N,K,L,D(2≤N,M≤1000,0≤K<M,0≤L<N,D≤2000)。

接下来D行,每行有4个用空格隔开的整数。第i行的4个证书Xi,Yi,Pi,OiXi,Yi,Pi,Oi,表示坐在位置(Xi,Yi)与(Pi,Oi)的两个同学会交头接耳(输入保证他们前后相邻或者左右相邻)。

输入数据保证最优秀方案的唯一性。

【输出】
共两行。

第一行包含KK个整数,a1,a2……ak,表示第a1行和a1+1行之间、第a2行和第a2+1行之间、…、第aK行和第aK+1行之间要开辟通道,其中ai<ai+1,每两个整数之间用空格隔开(行尾没有空格)。

第二行包含L个整数,b1b2……bL,表示第b1列和b1+1列之间,第b2列和b2+1列之间、…、第bL列和第bL+1列之间要开辟通道,其中bi<bi+1,每两个整数之间用空格隔开(行尾没有空格)。

【输入样例】
4 5 1 2 3
4 2 4 3
2 3 3 3
2 5 2 4
【输出样例】
2
2 4

题目有点长,但是本题考察的是贪心+排序;需要解决的问题是:找到横排的前k个、纵排的前l个;

  • 怎样找到横排的前k个,显然就是横排说话同学最多的横排,才最需要隔开,所以需要找横排说话同学最多的前k个;
  • 怎样找到纵排的前l个,同理。

方法一:贪心+快排

#include<bits/stdc++.h>
using namespace std;
#define N 1005
int aK[N], aL[N];//横排的前k个、纵排的前l个
int a1[N], b1[N];//横纵坐标出现的次数
int main(){
	int m, n, k, l, d, x1, y1, x2, y2;
	cin >> m >> n >> k >> l >> d;
	for(int i=1; i<=d; i++){//统计横纵坐标出现的次数
		cin >> x1 >> y1 >> x2 >> y2;
		if(x1 == x2)
			b1[(y1>y2)?y2:y1]++;
		else if(y1 == y2)
			a1[(x1>x2)?x2:x1]++;
	}
	for(int i=1; i<=k; i++){//通过比较大小,拿到a1数组(横坐标)中的前k值
		int mmax = 0, x;
		for(int j=1; j<=m; j++){
			if(a1[j] > mmax)
				mmax = a1[j], x = j;
		}
		aK[i] = x;
		a1[x] = 0;
	}
	for(int i=1; i<=l; i++){//通过比较大小,拿到b1数组(纵坐标)中的前l值
		int mmax = 0, x;
		for(int j=1; j<=n; j++){
			if(b1[j] > mmax)
				mmax = b1[j], x = j;
		}
		aL[i] = x;
		b1[x] = 0;
	}
	sort(aK+1, aK+k+1);
	sort(aL+1, aL+l+1);
	for(int i=1; i<=k; i++)
		cout << aK[i] << " ";
	cout << endl;
	for(int i=1; i<=l; i++)
		cout << aL[i] << " ";
	cout << endl;
	return 0;
}

方法二:贪心+结构体排序

#include<bits/stdc++.h>
using namespace std;
#define N 1005
struct node{
	int t, x;
}aK[N], bL[N];
bool cmp_big(node p, node q){
	return p.t > q.t;
}
bool cmp_small(node p, node q){
	return p.x < q.x;
}
int main(){
	int m, n, k, l, d, x1, y1, x2, y2;
	cin >> m >> n >> k >> l >> d;
	for(int i=1; i<=d; i++){
		cin >> x1 >> y1 >> x2 >> y2;
		if(x1 == x2){
			bL[(y1>y2)?y2:y1].t++;//t:出现次数times
			bL[(y1>y2)?y2:y1].x = (y1>y2)?y2:y1;//x:出现的数
		}
		else if(y1 == y2){
			aK[(x1>x2)?x2:x1].t++;
			aK[(x1>x2)?x2:x1].x = (x1>x2)?x2:x1;
		}
	}
	sort(aK+1, aK+m+1, cmp_big);//按照出现次数从大到小排序,找到前k个
	sort(bL+1, bL+n+1, cmp_big);//按照出现次数从大到小排序,找到前l个
	sort(aK+1, aK+k+1, cmp_small);//将前k个按照x(数)从小到大排序
	sort(bL+1, bL+l+1, cmp_small);//将前l个按照x(数)从小到大排序
	for(int i=1; i<=k; i++)
		cout << aK[i].x << " ";
	cout << endl;
	for(int i=1; i<=l; i++)
		cout << bL[i].x << " ";
	cout << endl;
	return 0;
}
发布了15 篇原创文章 · 获赞 10 · 访问量 209

猜你喜欢

转载自blog.csdn.net/qq_39053800/article/details/104249915