运动会

Author Avatar
Axell 1月 08, 2019
  • 在其它设备中阅读本文章

【问题描述】

小 F 和大 F 开了一所幼儿园,春天到了,幼儿园要举办一场运动会!
幼儿园里有 N 个小朋友,运动会里有 M 个项目可供选择,每个小朋友都对 M 个项目有一定的喜好程度。对于第 i 个小朋友,他第 j 喜欢的项目是 aij。并且保证对于每个小朋友,他都不会有两个一样喜欢的项目。
幼儿园的园长小 F 和副园长大 F 对运动会的事情头疼不已,她们希望玩的人数最多的项目玩的人数最少,否则她们在最受欢迎的项目举行时会忙不过来。她们希望从 M 个项目中选出若干个项目在运动会中举行(可以全选,但不能一个也不选),每个小朋友会且仅会玩一个项目,并且他玩的项目一定是举行的项目中他最喜欢的。
很不幸,今天幼儿园停电了,电脑不能用,小 F 和大 F 决定将这个问题交给聪明的你,请你求出玩的人数最多的项目玩的人数的最小值。

【输入】

第 1 行两个整数 N 和 M,表示小朋友的个数和备选运动项目的个数。
第 2 至 N+1 行,每行 M 个整数。第 i+1 行的第 j 个整数表示 aij,表示第 i 个小朋友第 j 喜欢的项目。保证 ai1..aiM 是 1..M 的一个排列。

【输出】

一个整数,表示玩的人数最多的项目玩的人数的最小值。

【样例 1】

4 5
5 1 3 4 2
2 5 3 1 4
2 3 1 4 5
2 5 4 3 1

2

【样例 1 解释】

一种最优方案是选择举行 1,3,4 三个项目,这样的话,4 个小朋友玩的项目分别是1,3,3,4,玩的人数最多的项目是 3,有 2 个人玩,所以答案是 2。

【样例 2】

3 3
2 1 3
2 1 3
2 1 3

3

【样例 2 解释】

由于无论怎么选择举行的项目,3 个小朋友玩的项目都是同一个,所以答案一定是 3。

【数据范围】

对于 30%的数据,M<=16。
对于另外 30%的数据,N<=3。
对于 100%的数据,1 <= N,M <= 200。

思路

由于需要删去一些项目,所以先假设全选,然后一项项删除,每次必须删除当前人数最多的项目,不然最多的永远是它且不会减少,每次统计答案即可

代码

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

int n,m,a[305][305],cnt[305],used[305],ans=1e9;

int get(int l){
    for (int i=1;i<=m;++i){
        if (used[a[l][i]]) continue;
        return a[l][i];
    }
    return -1;
}

int main(){
    cin>>n>>m;
    for (int i=1;i<=n;++i){
        for (int j=1;j<=m;++j){
            scanf("%d",&a[i][j]);
        }
    }
    for (int i=1;i<=m;++i){
        memset(cnt,0,sizeof(cnt));
        for (int j=1;j<=n;++j){
            cnt[get(j)]++;
        }
        int Tans=0,id=0;
        for (int j=1;j<=m;++j){
            if (Tans<cnt[j]){
                Tans=cnt[j];
                id=j;
            }
        }
        ans=min(ans,Tans);
        used[id]=1;
    }
    cout<<ans<<endl;
    return 0;
}

知识共享许可协议
本作品采用知识共享署名-非商业性使用-相同方式共享 3.0 未本地化版本许可协议进行许可。

本文链接:https://hs-blog.axell.top/archives/48/