2018山东冬令营 中国石油大学 运动会II

5838: 运动会II

时间限制: 1 Sec   内存限制: 128 MB
提交: 56   解决: 19
[ 提交][ 状态][ 讨论版]

题目描述

你打算举办一场运动会。有n个运动员和m个可供选择的运动项目,你要从m个项目中选出一个非空的子集。第i个运动员第j喜欢的项目是Ai,j,每个运动员会且仅会参加你选出的项目中他最喜欢的一个。你不希望参加某个项目的人数过多,因此你需要恰当地选出这个子集,使得最多人参加的项目的参加人数最少。

输入

第一行为两个整数n,m。
接下来n行,每行m个整数,第i行的第j个整数表示Ai,j

输出

输出一个整数,表示最多人参加的项目的参加人数最少是多少。

样例输入

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

样例输出

2

提示

对于20%的数据,保证1≤n,m≤10。
对于40%的数据,保证1≤n≤300,1≤m≤15。
对于70%的数据,保证1≤n,m≤300。
对于100%的数据,保证1≤n,m≤1000,Ai,1,Ai,2,...,Ai,m是一个排列。

来源

2018山东冬令营


类似于贪心的思想,每次去掉当前有的最大值,然后在所有最大值中找到最小值。

int map[1005][1005];
int fa[1005];
int del[1005]; 
int vis[1005];
int main()
{
    int n,m;
    int ans;
    scanf("%d%d",&n,&m);
    for(int i=1;i<=n;i++)
        for(int j=1;j<=m;j++)
            scanf("%d",&map[i][j]);
    for(int i=1;i<=n;i++)
    {
        fa[i]=1;//都默认是第一个 
        vis[map[i][1]]++; 
    } 
    ans=n;
    while(1)
    {
    //  printf("%d\n",ans);
        int flag=-1;
        for(int i=1;i<=m;i++)//开始寻找m个活动人数最多的那个 
        {
            if(del[i]==0)//如果当前这个活动没有删除 
            {
                if(flag==-1 || vis[i]>vis[flag])
                {
                    flag=i;
                }
            }
        }
        if(flag==-1)
            break;
        ans=min(ans,vis[flag]);
        del[flag]=1;
        for(int i=1;i<=n;i++)
        {
            int temp=fa[i];
            while(fa[i]<=m && del[map[i][fa[i]]])
                fa[i]++;
            if(temp!=fa[i])
                vis[map[i][fa[i]]]++;
        }
    }
    printf("%d\n",ans);
    return 0;
}

猜你喜欢

转载自blog.csdn.net/passer__/article/details/79462826
今日推荐