UPC训练赛17 问题 I: 运动会I

这篇博客介绍了一个关于幼儿园运动会项目选择的优化问题,旨在最小化玩得最多项目的人数。通过找到每个状态下的最大值并删除,逐步更新项目选择,最终得到最小人数。代码使用C++实现,通过遍历和计数方法找出解决方案。
摘要由CSDN通过智能技术生成

题目描述


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


输入


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


输出


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


样例输入


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

样例输出


2


整体思路


以整体视角看题目,每次找到当前状态下被选择最多的项目,然后将该项目删除,改变状态,之后对该状态重复操作,求出每次操作的最小值;

如样例;初始状态下为(5,2,2,2)最大值为3,指示项目2,之后删除项目2;

改变后的状态为(5,5,3,5)最大值为3,指示项目5,之后删除项目5;

改变后状态为(1,3,3,4)最大值为2,指示项目3,删除项目3;

改变后状态为(1,1,1,4)最大值为3,指示项目1,之后删除项目1;

改变后状态为(4,4,4,4)最大值为4,指示项目4,之后删除项目4;

所有项目删除,最小值是2,空间复杂度为O(m);


 

代码

#include<bits/stdc++.h>
using namespace std;
const int maxn=310,inf=1e9;
int m,n; 
int a[maxn][maxn];//表示第i个小朋友第j喜欢的项目
int cnt[maxn];//当前状态下项目i的参加人数
int now[maxn];//第i个小盆友项目选取的位置 
//相对于每一个小朋友的喜爱项目序列
int mp[maxn];//用来标记不选的项目
int ans=inf;//储存最小的玩的人数最多的项目的人数
int pos;//指示当前玩的人数最多的项目
int mx;//用来记录每个状态下的最多人数  
void input(){
	cin>>n>>m;
	for(int i=0;i<n;i++){
		for(int j=0;j<m;j++)
			scanf("%d",&a[i][j]);
	}
}//输入
void init(){
	for(int i=0;i<n;i++)
		cnt[a[i][now[i]]]++;
	//对每一个小盆友的第一喜爱项目进行计数
	
	for(int i=1;i<m;i++){
		mx=1; pos=-1;
		for(int j=1;j<=m;j++)
			if(!mp[j]&&mx<cnt[j]){
				mx=cnt[j];
				pos=j;
			}
		ans=min(ans,mx);
		//找到当前状态下项目最大值
		
		mp[pos]=1;
		//标记当前最大的项目,煽情该项目
		 
		for(int j=0;j<n;j++){
			if(mp[a[j][now[j]]]){
				while(mp[a[j][now[j]]])
					now[j]++;
				//修改小盆友的状态
				
				cnt[pos]--;
				cnt[a[j][now[j]]]++;
				//修改当前状态项目值 
			}			
		} 
	} 
} 
int main()
{
	input();
	init();
	printf("%d",ans); 
} 

看了大佬的代码,但是大佬不注释就很烦。

改自:(2条消息) 2022大中小学生联合训练第十七场_yhy and lly的博客-CSDN博客

 

  • 3
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

panjyash

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值