Loading

Loading

P14361 [CSP-S 2025] 社团招新 / club 题解

这是一道很考验细心的贪心题,挺有意思的。
思路比较简单:

  1. 每个人选满意度最高的部门是最优解,满意度最高的部门成为这个人的 首选部门
  2. 如果一个部门的首选人数超过\(\frac{n}{2}\) ,那么其他部门不再有首选人数超过\(\frac{n}{2}\)的可能性
  3. 当出现超过限制的情况时,为了让更多人选到首选部门,有些人需要换到次要部门(满意度排第二的部门),更换的过程会带来满意度的损失,所以我们选择损失最小的,降序即可。

考虑到每个人的满意度有三种,使用结构体维护,这样方便进行排序和处理。

我用a,b,c代表三个部门,fst代表首选部门,sec代表次要部门,pri代表损失(首选部门换成次要部门带来的损失),vis代表是否被访问。

flag代表是否超出限制,tmp统计每次处理的人数。

一边调一边想,写了好久,虽然很长,但是看起来比较清晰。

比我这个代码简单和快捷的题解应该很多吧。

#include<bits/stdc++.h>
using namespace std;
#define long long ll
int t,n;
struct pp{
	int a,b,c,fst,sec,pri;
	int vis=0;
}P[100010];
bool cmp1(pp x,pp y)
{
	return x.a>y.a;
}
bool cmp2(pp x,pp y)
{
	return x.b>y.b;
}
bool cmp3(pp x,pp y)
{
	return x.c>y.c;
}
bool cmp4(pp x,pp y)
{
	return x.pri<y.pri;
}
int tmp,tot,flag,cha;
int main()
{
	
	cin>>t;
	while(t--)
	{
		tot=0;
		cin>>n;
		for(int i=1;i<=n;i++)
		{
			cin>>P[i].a>>P[i].b>>P[i].c;
			if(P[i].a>=P[i].b&&P[i].b>=P[i].c)
			{
				P[i].fst=1,P[i].sec=2,P[i].pri=P[i].a-P[i].b;
			}else if(P[i].a>=P[i].c&&P[i].c>=P[i].b)
			{
				//a>c>b
				P[i].fst=1,P[i].sec=3,P[i].pri=P[i].a-P[i].c;
			}else if(P[i].b>=P[i].a&&P[i].a>=P[i].c)
			{
				//b>a>c
				P[i].fst=2,P[i].sec=1,P[i].pri=P[i].b-P[i].a;
			}else if(P[i].b>=P[i].c&&P[i].c>=P[i].a)
			{
				//b>c>a
				P[i].fst=2,P[i].sec=3,P[i].pri=P[i].b-P[i].c;
			}else if(P[i].c>=P[i].a&&P[i].a>=P[i].b)
			{
				//c>a>b
				P[i].fst=3,P[i].sec=1,P[i].pri=P[i].c-P[i].a;
			}else{
				//c>b>a
				P[i].fst=3,P[i].sec=2,P[i].pri=P[i].c-P[i].b;
			}
		}
		//第一部分
		tmp=0;
		sort(P+1,P+n+1,cmp1);
		flag=0;
		for(int i=1;i<=n;i++)
		{
			if(P[i].fst==1&&P[i].vis==0)
			{
				// tot+=P[i].a;
				// P[i].vis=1;
				tmp++;
			}
			if(tmp>n/2)
			{
				flag=1;
			//	break;
			}
		}
	//	cout<<tmp<<endl;
		cha=tmp-n/2;
		tmp=0;
		
		if(!flag)
		{
			for(int i=1;i<=n;i++)
			{
				if(P[i].fst==1&&P[i].vis==0)
				{
					tot+=P[i].a;
					P[i].vis=1;
					tmp++;
				}
				if(tmp>=n/2)
				{
					break;
				}
			}
		}else{
			
			sort(P+1,P+n+1,cmp4);
			tmp=0;
			for(int i=1;i<=n;i++)
			{
				if(!P[i].vis&&P[i].fst==1)
				{
					tmp++;
					if(P[i].sec==1)
					{
						tot+=P[i].a;
					}else if(P[i].sec==2)
					{
						tot+=P[i].b;
					}else{
						tot+=P[i].c;
					}
					P[i].vis=1;
				}
				if(tmp>=cha) break;
			}
			sort(P+1,P+n+1,cmp1);
			tmp=0;
			for(int i=1;i<=n;i++)
			{
				if(P[i].fst==1&&P[i].vis==0)
				{
					tot+=P[i].a;
					P[i].vis=1;
					tmp++;
				}
				if(tmp>=n/2) break;
			}
		}
		//第二部分
		flag=0;
		tmp=0;
		sort(P+1,P+1+n,cmp2);
		for(int i=1;i<=n;i++)
		{
			if(P[i].fst==2&&P[i].vis==0)
			{
				tmp++;
			}
			if(tmp>n/2)
			{
				flag=1;
			}
		}
		cha=tmp-n/2;
		tmp=0;
		
		if(!flag)
		{
			//cout<<"in2"<<endl;
			for(int i=1;i<=n;i++)
			{
				if(P[i].fst==2&&P[i].vis==0)
				{
					tot+=P[i].b;
					P[i].vis=1;
					tmp++;
				}
				if(tmp>=n/2)
				{
					break;
				}
			}
		}else{
			
			sort(P+1,P+n+1,cmp4);
			tmp=0;
			for(int i=1;i<=n;i++)
			{
				if(!P[i].vis&&P[i].fst==2)
				{
					tmp++;
					if(P[i].sec==1)
					{
						tot+=P[i].a;
					}else if(P[i].sec==2)
					{
						tot+=P[i].b;
					}else{
						tot+=P[i].c;
					}
					P[i].vis=1;
				}
				if(tmp>=cha) break;
			}
			sort(P+1,P+n+1,cmp2);
			tmp=0;
			for(int i=1;i<=n;i++)
			{
				if(P[i].fst==2&&P[i].vis==0)
				{
					tot+=P[i].b;
					P[i].vis=1;
					tmp++;
				}
				if(tmp>=n/2) break;
			}
		}
		
		//第三部分
		flag=0;
		tmp=0;
		sort(P+1,P+1+n,cmp3);
		for(int i=1;i<=n;i++)
		{
			if(P[i].fst==3&&P[i].vis==0)
			{
				// tot+=P[i].a;
				// P[i].vis=1;
				tmp++;
			}
			if(tmp>n/2)
			{
				flag=1;
			//	break;
			}
		}
		cha=tmp-n/2;
		tmp=0;
		
		if(!flag)
		{
			//cout<<"in3"<<endl;
			for(int i=1;i<=n;i++)
			{
				if(P[i].fst==3&&P[i].vis==0)
				{
					tot+=P[i].c;
					P[i].vis=1;
					tmp++;
				}
				if(tmp>=n/2)
				{
					break;
				}
			}
		}else{
			
			sort(P+1,P+n+1,cmp4);
			tmp=0;
			for(int i=1;i<=n;i++)
			{
				if(!P[i].vis&&P[i].fst==3)
				{
					tmp++;
					if(P[i].sec==1)
					{
						tot+=P[i].a;
					}else if(P[i].sec==2)
					{
						tot+=P[i].b;
					}else{
						tot+=P[i].c;
					}
					P[i].vis=1;
				}
				if(tmp>=cha) break;
			}
			sort(P+1,P+n+1,cmp3);
			tmp=0;
			for(int i=1;i<=n;i++)
			{
				if(P[i].fst==3&&P[i].vis==0)
				{
					tot+=P[i].c;
					P[i].vis=1;
					tmp++;
				}
				if(tmp>=n/2) break;
			}
		}
		cout<<tot<<endl;
		for(int i=1;i<=n;i++)
		{
			P[i].vis=0;
		}
	//	tot=0,tmp=0,flag=0;
	}
	return 0;
}
posted @ 2025-11-09 13:58  Miya555  阅读(7)  评论(0)    收藏  举报