1982: D.房间安排

1982: D.房间安排

时间限制: 2 Sec  内存限制: 256 MB
提交: 243  解决: 30
[ 提交][ 状态][ 讨论版]

题目描述

Alice所在的社团计划一次外出游玩。Alice需要安排所有人入住的房间。社团一共订了n个房间,然后Alice给第i间房间安排了ai(0<=ai<=4)个人。向旅馆提交了住宿信息之后,Alice发现如果出现一个房间人数为1或者为2的情况,这个房间的社员就会感觉到孤独和凄凉,会很失望。所以Alice现在想调整一下,把某些社员调到其他房间,使得所有社员都不会感到孤独。但是为了避免不必要的麻烦,她希望调整的人数最少。Alice向Bob求助,Bob希望你能写个程序求出最少需要调整的人数。

注意:你可以把一个房间的初始人员都调出去,允许房间空闲,不允许某个房间人数超过4个。

输入

第一行输入一个整数n(1<=n<=1000000),表示预定的房间数量。

接下来一行输入n个数,第i个数是ai(0<=ai<=4),表示第i个房间初始有ai个人。

输出

输出一个数,表示最少需要调整的人的数量,如果无论怎么安排都不能满足要求,输出-1。

样例输入

51 2 2 4 340 3 0 4

样例输出

20

提示


第一个样例最少需要调动2个人,将第一个房间的一个人调到第二个房间,从第四个房间调一个人到第三个房间,最后人数为0 3 3 3 3,满足要求。



第二个样例不需要调动,所以答案是0

来源

第六届河海大学程序设计大赛  

当时做了两个多小时,硬是没做出来,回来继续按着思路写,然后就ok了。

思路:

1,2,3,4的房间分别记录下来,当1等于2的时候,正好完全补上,当1大于2时,按照剩下的1自己组成3,然后余下的一个1或者2个1分别讨论,当1小于2时,剩下的2正好3个2需要移动两个,余下1个2或者两个2分别讨论即可。

#include<iostream>
#include<cstring>
using namespace std;
int a[1000050];
int main()
{
	long long n;
	while(cin>>n)
	{
		long long more[5],cnt=0;
		memset(more,0,sizeof(more));
		for(long long i=1;i<=n;i++)
		{
			cin>>a[i];
			more[a[i]]++;
		}
		for(int i=1;i<=4;i++)
		{
			cnt+=more[i]*i;
		}
		if(cnt<3||cnt==5)
		{
			cout<<"-1"<<endl;
			continue;
		}
		if(more[1]==more[2])
		{
			cout<<more[1]<<endl;
			continue;
		}
		else
		{
			if(more[1]>more[2])
			{				
				int temp=more[2];
				int t=more[1]-more[2];
				temp+=t/3*2;
				if(t%3==1)
				{
					if(more[3]+more[2]+t/3>=1)
					temp++;
					else
					{
						if(more[4]>=2)
						{
							temp+=2;
						}
						else
						{
							cout<<"-1"<<endl;
							continue;
						}
					}
				}
				if(t%3==2)
				{
					if(more[4]>=1)
					{
						temp+=2;
					}
					else
					{
						if(more[3]+t/3+more[2]>=2)
						{
							temp+=2;
						}
						else
						{
							cout<<"-1"<<endl;
							continue;
						}
					}
				}
				cout<<temp<<endl;
				continue;
			}
			if(more[1]<more[2])
			{
				int temp=more[1];
				int t=more[2]-more[1];
				temp+=t/3*2;
				if(t%3==1)
				{
					if(more[4]>=1)
					temp++;
					else
					{
						if(more[3]+more[2]+t/3>=2)
						{
							temp+=2;
						}
						else
						{
							cout<<"-1"<<endl;
							continue;
						}
					}
				}
				if(t%3==2)
				{
					temp+=2;
				}
				cout<<temp<<endl;
				continue;
			}
		}
	}
	return 0;
}


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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

没想好叫什么名字

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

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

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

打赏作者

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

抵扣说明:

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

余额充值