The Feast and the Bus CodeForces - 1250B(枚举+暴力)

Employees of JebTrains are on their way to celebrate the 256-th day of the year! There are n employees and k teams in JebTrains. Each employee is a member of some (exactly one) team. All teams are numbered from 1 to k. You are given an array of numbers t1,t2,…,tn where ti is the i-th employee’s team number.

JebTrains is going to rent a single bus to get employees to the feast. The bus will take one or more rides. A bus can pick up an entire team or two entire teams. If three or more teams take a ride together they may start a new project which is considered unacceptable. It’s prohibited to split a team, so all members of a team should take the same ride.

It is possible to rent a bus of any capacity s. Such a bus can take up to s people on a single ride. The total cost of the rent is equal to s⋅r burles where r is the number of rides. Note that it’s impossible to rent two or more buses.

Help JebTrains to calculate the minimum cost of the rent, required to get all employees to the feast, fulfilling all the conditions above.

Input
The first line contains two integers n and k (1≤n≤5⋅105,1≤k≤8000) — the number of employees and the number of teams in JebTrains. The second line contains a sequence of integers t1,t2,…,tn, where ti (1≤ti≤k) is the i-th employee’s team number. Every team contains at least one employee.

Output
Print the minimum cost of the rent.

Examples
Input
6 3
3 1 2 3 2 3
Output
6
Input
10 1
1 1 1 1 1 1 1 1 1 1
Output
10
Input
12 4
1 2 3 1 2 3 4 1 2 1 2 1
Output
12
思路:这个题能过真的是幸运。我先说说我的做法,我们肯定优先考虑一次运两个队伍,那么我们把所有的两支队伍的情况计算出来,再加上最多的那一支队伍的人数,排序去重之后,枚举不断的更新最小值。极限过题,说实话我自己都没想到能过。
代码如下:

#include<bits/stdc++.h>
#define ll long long
#define inf 0x3f3f3f3f
using namespace std;

const int maxx=5e5+100;
const int maxn=8e3+100;
int a[maxx];
int num[maxx],vis[maxx];
int val[maxn*maxn];
int n,k;

inline void init()
{
	for(int i=0;i<=k;i++) num[i]=0;
}
inline ll check(int x)
{
	memset(vis,0,sizeof(vis));
	int cnt=0;
	for(int i=1;i<=k;i++)
	{
		if(vis[i]) continue;
		if(num[i]>x) return inf;
		int pos=0;
		for(int j=k;j>=1;j--)
		{
			if(vis[j]==0&&num[i]+num[j]<=x)
			{
				vis[j]=1;
				pos=j;
				break;
			}
		}
		vis[i]=vis[pos]=1;
		cnt++;
	}
	return cnt*x;
}
int main()
{
	scanf("%d%d",&n,&k);
	init();
	for(int i=1;i<=n;i++) scanf("%d",&a[i]),num[a[i]]++;
	sort(num+1,num+1+k);
	int len=0;
	for(int i=1;i<=k;i++)
	for(int j=i+1;j<=k;j++) if(num[i]+num[j]>num[k]) val[++len]=num[i]+num[j];
	val[++len]=num[k];
	sort(val+1,val+1+len);
	len=unique(val+1,val+1+len)-val-1;
	ll ans=check(val[1]);
	for(int i=2;i<=len;i++)
	{
		ll zz=check(val[i]);
		ans=min(ans,zz);
	}
	cout<<ans<<endl;
	return 0;
}

在这里插入图片描述2000ms的题目。。
正解:其实也是暴力枚举,最终搭载的人数范围肯定在人数最多的那支队伍人数~两支队伍加起来的最多人数。那么我们就枚举这段范围,对于这段范围我们去求花费的价值,对于两支队伍,我们肯定希望在允许的范围内凑得人越多越好(这里比我的程序优化很多),那么我们分别从两头开始枚举,不断的更新最小值。
代码如下:

#include<bits/stdc++.h>
#define ll long long
using namespace std;

const int maxx=5e5+100;
const int maxm=8e3+100;
int a[maxx],num[maxm];
int n,k;

int main()
{
	scanf("%d%d",&n,&k);
	memset(num,0,sizeof(num));
	for(int i=1;i<=n;i++) scanf("%d",&a[i]),num[a[i]]++;
	sort(num+1,num+1+k);
	int _max=num[k];
	for(int i=1;i<=k;i++)
	for(int j=i+1;j<=k;j++) _max=max(_max,num[i]+num[j]);
	ll ans=1e18;
	for(int i=num[k];i<=_max;i++)
	{
		int l=1,r=k;
		int cnt=0;
		while(l<=r)
		{
			++cnt;
			if(l!=r&&num[l]+num[r]<=i) ++l,r--;//这里一开始没有想到,对于最大的那个来说,如果最小的都不满足,那么它肯定是自己走了。
			else r--;
		}
		ans=min(ans,(ll)cnt*i);
	}
	cout<<ans<<endl;
	return 0;
}

在这里插入图片描述优化后快一倍,嘤嘤嘤
努力加油a啊,(o)/~

发布了617 篇原创文章 · 获赞 64 · 访问量 5万+

猜你喜欢

转载自blog.csdn.net/starlet_kiss/article/details/105253289
今日推荐