洛谷 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;
}