CSP历年复赛题-P1056 [NOIP2008 普及组] 排座椅
原题链接:https://www.luogu.com.cn/problem/P1056
题意解读:计算k行、l列通道的位置,使得上课讲话的人最少。
解题思路:贪心法。
贪心策略:通道应该优先设置在讲话人数最多的地方。
1、枚举所有交头接耳的同学(x,y) (p,q)
2、如果在同一行,即x==p,则y列和q列有一对交头接耳,算在列号较小者上min(y,q),通过桶数组col进行累加,同时记录列号min(y,q)
3、如果在同一列,即y==q,则x行和p行有一对交头接耳,算在行号较小者上min(x,p),通过桶数组row进行累加,同时记录行号min(x,p)
4、分别将row、col按照交头接耳对数由大到小排序,在row中取前k个行号存入vector,col中取l个行号存入vector
5、将行、列结果分别由小到大排序
6、输出即可
100分代码:
#include <bits/stdc++.h>
using namespace std;
const int N = 1005;
int m, n, k, l, d;
struct node
{
int xy, cnt;
};
node row[N]; //row[i]存第i行和i+1行之间有几对同学讲闲话
node col[N]; //col[i]存第i列和i+1列之间有几对同学讲闲话
bool cmp(node a, node b)
{
return a.cnt > b.cnt;
}
vector<int> ansrow;
vector<int> anscol;
int main()
{
cin >> m >> n >> k >> l >> d;
int x, y, p, q;
while(d--)
{
cin >> x >> y >> p >> q;
if(x == p) //讲闲话的两人在同一行
{
int mincol = min(y, q);
col[mincol].xy = mincol;
col[mincol].cnt++;
}
if(y == q) //讲闲话的两人在同一列
{
int minrow = min(x, p);
row[minrow].xy = minrow;
row[minrow].cnt++;
}
}
sort(row + 1, row + m + 1, cmp);
sort(col + 1, col + n + 1, cmp);
//选讲闲话最多的前k行
for(int i = 1; i <= k; i++) ansrow.push_back(row[i].xy);
//选讲闲话最多的前l列
for(int i = 1; i <= l; i++) anscol.push_back(col[i].xy);
sort(ansrow.begin(), ansrow.end());
sort(anscol.begin(), anscol.end());
for(int v : ansrow) cout << v << " ";
cout << endl;
for(int v : anscol) cout << v << " ";
}