ICode9

精准搜索请尝试: 精确搜索
首页 > 编程语言> 文章详细

针对数据的特殊性,设计算法

2021-11-30 11:03:37  阅读:198  来源: 互联网

标签:针对 特殊性 k1 k3 k2 算法 蛋糕 半径 次数


 

在我的理解中,许多计算机算法是针对某个特殊的问题来设计算法,也就是说这个问题并不是“普适”,而它的特殊性就体现在数据的范围上,所以我们应该提高对数据的敏感度,寻找合适的突破口来解决整个问题。以下面这个问题为例:
堆蛋糕
其实小布是一个十分犀利的蛋糕师。他最喜欢的食物就是蛋糕。一天,他自己做出了N个圆柱状的蛋糕,每个蛋糕 都有一个底面圆的半径Ri。高度都是一样的。小布在开始享用他的蛋糕大餐之前忽然觉得,圆柱状的蛋糕没有什么 诱惑力。小布看到了别人结婚用的蛋糕都是很多很多层的,那样的蛋糕才比较给力。但是堆太多层的蛋糕比较困难 ,于是小布想要堆出许多三层的蛋糕,再开始自己的蛋糕大餐。当然,作为蛋糕师,小布在堆蛋糕的时候不会对蛋 糕的形状有任何破坏,而且,小布希望三层蛋糕的半径从上往下严格递增。这才是一个普通的好蛋糕。但是小布在 考虑一个十分重要的问题,最多可以堆出多少三层蛋糕呢?

Input
输入第一行仅包含一个整数N,表示蛋糕的数量。
接下来N个整数,表示每个蛋糕半径的大小Ri。
N<=3,000,000 Ri<=N

Output
输出一行仅包含一个整数,表示最多可以做成多少个蛋糕

Samples
输入数据 1
6
1 2 3 4 3 2
输出数据 1
2

拿到问题后,我们可以发现以下几个问题:
1:N小于等于3e6,这就说明N平方的算法是不可能通过的。
2:蛋糕半径R小于3e6,这就意味着我们可能对R进行桶排,找出某个半径出现的次数。
3:每个蛋糕只堆3层,3是一个比较小的数字了。
4:蛋糕的组成,只要3层的半径呈现一个递增的数列就好了。

于是拿样例来看,我们可以先统计出每种半径出现的次数,得到如下结果
半径值 1 2 3 4
出现次数 1 2 2 1
接下来本题最关键的点到了,我们如何完成数字之间的配对。也就是说
如果我们让半径值为(1,2,4)组成一个蛋糕后,剩下的半径值为(2,3,3),就再不能组成新的蛋糕了,而事实上我们可以组成(1,2,3),(2,3,4)这2个蛋糕出来。也就是说由于每种半径出现的次数是不一样的,此时为了组成尽可能多的蛋糕,我们应该尽量先使用次数较多的数字,而不是使用出现次数较小的,因为这样会导致后期会现有蛋糕的数量较多,但种类却没有3种的尴尬局面。
总结本题求解过程:
1:求出每个半径出现的次数,由于每次都要找出出现次数最大的3个数字,所以我们可以将其丢到大根堆中。
2:不断从堆中取出3个数字a,b,c出来,并且a>=b>=c,于是可能组成c个蛋糕出来。
3:将没有用完的蛋糕丢回堆中,即a-c与b-c的值.
4:重复执行(2),(3)步骤直至堆中的元素不足3类。

代码如下:

#include<bits/stdc++.h>
using namespace std;
int n,x,kinds,k1,k2,k3,ans=0;
int num[3000010]={0};
priority_queue<int>d;
int main()
{
	scanf("%d",&n);
	kinds=0;
	
	for(int i=1;i<=n;i++)
	{
		scanf("%d",&x);
		num[x]++;	
	}
	for(int i=1;i<3000010;i++)
		if(num[i]>0)
				d.push(num[i]);
	while(d.size()>=3)
	{
		
		k1=d.top();
		d.pop();
		k2=d.top();
		d.pop();
		k3=d.top();
		d.pop();
		k1=k1-k3;
		k2=k2-k3;
		if(k1>0)
			d.push(k1);
		if(k2>0)	
			d.push(k2);
		ans=ans+k3;
		k3=0;
		
	}
	printf("%d",ans);
	
	return 0;			
}

  

然而当我再拿到这个题时,我的思维又被打开了.
组建部门
EYENCE有N个部门,其中A i员工属于第i个部门(1≤i≤N)。没有员工属于多个部门。 该公司正在计划跨部门的项目。每个项目将由从K个不同部门中,每个部门选出一个人,共K名员工组成。 最多可以做多少个项目?没有员工可以参与多个项目

Input
第一行给出N,K 接下来给出N个数字,代表a1....an
1≤K≤N≤2×10^5
1≤Ai​≤10^12

Output
如题

样例输入
3 3
2 3 4

样例输出
2

题解:这个题与上一个题大同小异,都是不断一个数列中取出权值最大的K个数字,设为
a1,a2,a3....ak且a1>=a2>=a3>=....aK.然后再将a1-ak,a2-ak,a3-ak.....的值丢回原数列。
但上个题中因为K的值较小,我们可以用堆来完成,此题K的值很大,明显不适合做为突破口。

 

标签:针对,特殊性,k1,k3,k2,算法,蛋糕,半径,次数
来源: https://www.cnblogs.com/oiteacher/p/15623221.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有