洛谷P1056排座椅 贪心思想

洛谷 P1056 排座椅
基本思路:

用 row[ i ] 表示第 i 行和第 i+1 行之间作为通道的话,可以减少多少对交头接耳的学生。
用 col[ i ] 表示第 i 列和第 i+1 列之间作为通道的话,可以减少多少对交头接耳的学生。
在输入数据的时候即可确定row[]和col[]
然后分别取各自前K/L个大的元素的下标,在顺序排列输出即可。
AC代码:

#include <bits/stdc++.h>
#define maxn 1005
using namespace std;

int m, n, k, l, d;

int row[maxn];//row[i]表示第i行和第i+1行之间作为通道的话,可以减少多少对交头接耳的学生。 
int col[maxn];//col[i]表示第i列和第i+1列之间作为通道的话,可以减少多少对交头接耳的学生。

int vis[maxn];
int res[maxn];
int main(int argc, char *argv[]) {
	cin>>m>>n>>k>>l>>d;
	int x,y,p,q;
	for(int i=0; i<d; i++){
		cin>>x>>y>>p>>q;
		if(x == p){
			//在同一行
			int r = min(y, q);
			col[r]++; 
		}
		else if(y == q){
			//在同一列
			int r = min(x, p);
			row[r]++; 
		}
	}
	//取row[]中最大的k个数的序列,放入结果集中
	for(int i=0; i<k; i++){
		int maxIndex = -1;
		int pmax = 0;
		for(int j=m-1; j>=0; j--){
			if(!vis[j] && row[j] > pmax){
				pmax = row[j];
				maxIndex = j;
			}
		}
		res[i] = maxIndex;
		vis[maxIndex] = 1;
	}
	sort(res, res+k);
	for(int i=0; i<k; i++){
		cout<<res[i];
		if(i != k-1)
			cout<<' ';
	}
	cout<<endl;
	//取col[]中最大的l个数的序列,放入结果集中
	memset(vis, 0, sizeof(vis));
	for(int i=0; i<l; i++){
		int maxIndex = -1;
		int pmax = 0;
		for(int j=n-1; j>=0; j--){
			if(!vis[j] && col[j] > pmax){
				pmax = col[j];
				maxIndex = j;
			}
		}
		res[i] = maxIndex;
		vis[maxIndex] = 1;
	}
	sort(res, res+l);
	for(int i=0; i<l; i++){
		cout<<res[i];
		if(i != l-1)
			cout<<' ';
	}
	cout<<endl;
	return 0;
}

改进:
其中,需要求row[]中前k个大的数的下标,并按从小到大的顺序输出,上述给出的代码在这里处理的时间复杂度为O(n^2),下面改进为O(logn):
把 row[ i ] 和 i 一同存储下来,编写一个如下的:

struct State{
	int L;//第i行或第i列 
	int num;//当前行或列作为通道,可以减少的交头接耳的学生的对数 
	friend bool operator < (State a, State b){
		return a.num<b.num;//num大的优先级高 
	}
};

然后定义一个包含该元素的优先队列:

priority_queue<State> qr;

再把row[ i ] 和 i 依次作为State放入qr中,由于提前设定了结构体State的优先级规则,所有排在qr队首的一定是值最大的元素。依次取k次队首,便可以得到想要的所有元素的序列,然后排序输出即可,代码如下:

#include <bits/stdc++.h>
#define maxn 1005
using namespace std;

int m, n, k, l, d;

int row[maxn];//row[i]表示第i行和第i+1行之间作为通道的话,可以减少多少对交头接耳的学生。 
int col[maxn];//col[i]表示第i列和第i+1列之间作为通道的话,可以减少多少对交头接耳的学生。

vector<int> res;

struct State{
	int L;//第i行或第i列 
	int num;//当前行或列作为通道,可以减少的交头接耳的学生的对数 
	friend bool operator < (State a, State b){
		return a.num<b.num;//num大的优先级高 
	}
};

int main(int argc, char *argv[]) {
	cin>>m>>n>>k>>l>>d;
	int x,y,p,q;
	for(int i=0; i<d; i++){
		cin>>x>>y>>p>>q;
		if(x == p){
			//在同一行
			int r = min(y, q);
			col[r]++; 
		}
		else if(y == q){
			//在同一列
			int r = min(x, p);
			row[r]++; 
		}
	}
	priority_queue<State> qr;
	priority_queue<State> qc;
	//取row[]中最大的k个数的序列,放入结果集中
	for(int i=1; i<m; i++){//先把row[]所有数据放入优先队列qr中 
		qr.push({i, row[i]});
	}
	for(int i=0; i<k; i++){//从qr中取出前k个,放入结果集res中 
		State t = qr.top();
		qr.pop();
		res.push_back(t.L);
	}
	sort(res.begin(), res.end());
	for(int i=0; i<res.size(); i++){
		cout<<res[i];
		if(i != k-1){
			cout<<' ';
		}
	}
	cout<<endl;
	//取col[]中最大的l个数的序列,放入结果集中
	res.clear();
	for(int i=1; i<n; i++){
		qc.push({i, col[i]});
	}
	for(int i=0; i<l; i++){
		State t = qc.top();
		qc.pop();
		res.push_back(t.L);
	}
	sort(res.begin(), res.end());
	for(int i=0; i<res.size(); i++){
		cout<<res[i];
		if(i != l-1){
			cout<<' ';
		}
	}
	cout<<endl;
	return 0;
}
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值