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 << " ";
}

 

posted @ 2024-05-27 15:08  五月江城  阅读(42)  评论(0编辑  收藏  举报