星星之火

[AGC018 B] Sports Festival 解题报告

题目链接:https://agc018.contest.atcoder.jp/tasks/agc018_b

题目:

题目大意:

有N个人参加M个体育项目,每个人对体育项目的喜爱程度有一个排名,A[i][j]表示第i个人第j喜欢的体育项目,每个人会参加存在的体育项目中他最喜欢的。现在我们需要选出一些体育项目,使得参加人数最多的体育项目参加的人数最少化

题解:

先将所有的体育项目选上,找出参加人数最多的项目

假设去掉的体育项目中不包括这个项目,参加人数最多的项目拥有的人数一定不变

那么考虑我们每次把参加人数最多的项目删掉,再计算现在参加人数最多的项目,在整个过程中取ans=min(ans,当前参加人数最多的项目拥有的人数)

时间复杂度$O(NM^2$)

AC代码如下:

#include<algorithm>
#include<cstring>
#include<iostream>
#include<cstdio>
using namespace std;

const int N=300+15;
const int inf=1e9+7;
int n,m,ans;
int a[N][N],vis[N],num[N];
inline int read()
{
    char ch=getchar();
    int s=0,f=1;
    while (ch<'0'||ch>'9') {if (ch=='-') f=-1;ch=getchar();}
    while (ch>='0'&&ch<='9') {s=(s<<3)+(s<<1)+ch-'0';ch=getchar();}
    return s*f;
}
int main()
{
    n=read();m=read();
    for (int i=1;i<=n;i++)
        for (int j=1;j<=m;j++)
            a[i][j]=read();
    ans=inf;
    for (int i=1;i<=m;i++)
    {
        memset(num,0,sizeof(num));
        for (int j=1;j<=n;j++)
            for (int k=1;k<=m;k++)
                if (!vis[a[j][k]])
                {
                    num[a[j][k]]++;
                    break;
                }
        int s,tans=0;
        for (int j=1;j<=m;j++)
        {
            if (tans<num[j])
            {
                s=j;
                tans=num[j];
            }
        }
        vis[s]=1;
        ans=min(ans,tans);
    }
    printf("%d\n",ans);
    return 0;
}

 

posted @ 2018-08-26 16:52  星星之火OIer  阅读(249)  评论(0编辑  收藏  举报