【Codeforces】Codeforces Round #207 (Div. 1) C. Compartments | 贪心

124 阅读3分钟

持续创作,加速成长!这是我参与「掘金日新计划 · 1 月更文挑战」的第21天,点击查看活动详情

【Codeforces】Codeforces Round #207 (Div. 1) C. Compartments | 贪心

题目链接

Problem - 356C - Codeforces

题目

A team of students from the city S is sent to the All-Berland Olympiad in Informatics. Traditionally, they go on the train. All students have bought tickets in one carriage, consisting of nn compartments (each compartment has exactly four people). We know that if one compartment contain one or two students, then they get bored, and if one compartment contain three or four students, then the compartment has fun throughout the entire trip.

The students want to swap with other people, so that no compartment with students had bored students. To swap places with another person, you need to convince him that it is really necessary. The students can not independently find the necessary arguments, so they asked a sympathetic conductor for help. The conductor can use her life experience to persuade any passenger to switch places with some student.

However, the conductor does not want to waste time persuading the wrong people, so she wants to know what is the minimum number of people necessary to persuade her to change places with the students. Your task is to find the number.

After all the swaps each compartment should either have no student left, or have a company of three or four students.

题目大意

nn 个非负整数数组 a1,a2,...,ana_1,a_2,...,a_n,每个操作选择任意两个非负整数 ai,aja_i,a_j 使得其中一个增加 1 另一个减小 1。任意时刻数组中的数字 aia_i 应该满足 0ai40\le a_i\le 4

问最小的操作次数使得数组中仅包含 0,3,40,3,4,无解输出 -1。

思路

首先我们先看在什么情况下是无解的:求得所有的数之和 sumsum,我们可以将原问题看做将 sumsum 拆分成 t3t_3 个 3 和 t4t_4 个 4,使得 t3×3+t4×4=sum,t3+t4nt_3\times 3+t_4\times 4=sum,t_3+t_4\le n,且 t3,t4t_3,t_4 是非负整数。第二个条件必然满足。由系数为正数的二元一次不定方程的非负解和正解的性质可知 t3×3+t4×4t_3\times 3+t_4\times 4 可以表示出大于 5 的所有正整数。所以我们可以轻松发现当 sumsum1,2,51,2,5 时应该输出 -1。

在本题中数组的顺序无关紧要,我们直接分别统计原数组中 1,2,3,41,2,3,4 的数量即可。

枚举 t4t_4,则可以相应求出 t3t_3。贪心的求得将原数组中的元素转变为t3t_3 个 3 和 t4t_4 个 4 需要的步数,即尽可能将本来较大的数变大,统计所有合法解的最小值即可获得最优解。

代码

#include <bits/stdc++.h>
#define nnn printf("No\n")
#define yyy printf("Yes\n")
using namespace std;
using LL=long long;
typedef pair<int,int> PII;
const int N=500001;
const LL mod=1000000007;
//const LL mod=998244353;

priority_queue<pair<int,int>,vector<pair<int,int>>,greater<pair<int,int>>> que;
vector<int> e[N];
int f[N],x,y,z;
int n,m,k;
void bcjInit() {for (int i=1;i<=n;++i) f[i]=i;}
int find(int x) {return f[x]==x?x:f[x]=find(f[x]);}
LL gcd(LL x,LL y) {return y==0?x:gcd(y,x%y);}
long long solve()
{
	int x,cnt1=0,cnt2=0,cnt3=0,cnt4=0;
	scanf("%d",&n);
	int sum=0;
	while (n--)
	{
		cin>>x;
		sum+=x;
		if (x==1) cnt1++;
		if (x==2) cnt2++;
		if (x==3) cnt3++;
		if (x==4) cnt4++;
	}
	if (sum==1||sum==2||sum==5) return -1;
	if (cnt1==0&&cnt2==0) return 0;
	int ans,outpt=sum,a1,a2,a3,a4,p3,p4;
	for (int t3,t4=0,t;t4*4<=sum;++t4)
	{
		t3=(sum-t4*4)/3;
		if (t3*3+t4*4!=sum) continue;
		p3=t3;
		p4=t4;
		a2=cnt2;
		a3=cnt3;
		a4=cnt4;
		ans=0;
		
		t=min(p4,a4);
		p4-=t;
		a4-=t;
		t=min(p4,a3);
		ans+=t;
		a3-=t;
		p4-=t;
		t=min(p4,a2);
		ans+=2*t;
		a2-=t;
		p4-=t;
		ans+=3*p4;
		
		p3-=min(p3,a3);
		p3-=min(p3,a4);
		t=min(p3,a2);
		ans+=t;
		a2-=t;
		p3-=t;
		ans+=p3*2;
		outpt=min(outpt,ans);
	}
	return outpt;
//	scanf("%d",&m);
//	scanf("%d",&k);
}
int main()
{
	int T=1;
//	for (scanf("%d",&T);T--;)
//        if (solve()) yyy;
//        else nnn;

//	for (scanf("%d",&T);T--;) solve();

	cout<<solve();
	return 0;
}