分析:
显然最坏情况就是我们每个项目都选择,就可以得到一个答案上限
贪心的,如果我们想让答案减少,就找到当前被选择次数最多的体育项目刨除
至于那些选择了这个项目的运动员,顺延一下就好了
(可以证明这个贪心的正确性)
时间复杂度:
O(nm)
O
(
n
m
)
tip
hu测的时候没有立刻想到正解,
先想到了二分,然而在考虑如何二分判定的时候发现了正解
所以还是那个原则:相信自己,仔细分析
#include<cstdio>
#include<cstring>
#include<iostream>
using namespace std;
const int N=1002;
int n,m,ans=0;
int a[N][N],cnt[N],b[N];
bool vis[N];
void solve() {
memset(b,0,sizeof(b));
memset(vis,1,sizeof(vis));
int maxx=0,k;
for (int i=1;i<=n;i++) {
cnt[i]=1; //选择了哪一个
b[a[i][cnt[i]]]++;
if (b[a[i][cnt[i]]]>maxx)
maxx=b[a[i][cnt[i]]],k=a[i][cnt[i]];
}
ans=maxx;
int ans_2;
bool flag=1;
for (int T=1;T<=m&&flag;T++) {
vis[k]=0; b[k]=0;
ans_2=0;
for (int i=1;i<=n;i++)
if (a[i][cnt[i]]==k) {
while (!vis[a[i][cnt[i]]]&&cnt[i]<=m)
cnt[i]++;
if (cnt[i]>m) {flag=0;break;}
b[a[i][cnt[i]]]++;
}
if (!flag) break;
for (int i=1;i<=m;i++)
if (vis[i]&&b[i]>ans_2)
ans_2=b[i],k=i;
ans=min(ans,ans_2);
}
printf("%d\n",ans);
}
int main()
{
freopen("sports.in","r",stdin);
freopen("sports.out","w",stdout);
scanf("%d%d",&n,&m);
for (int i=1;i<=n;i++)
for (int j=1;j<=m;j++)
scanf("%d",&a[i][j]);
solve();
return 0;
}