共同富裕

@共同富裕
描述

给定一个数组A1, A2, … AN,每次操作可以从中选定一个元素Ai,把除了Ai之外的所有元素都加1。

问最少几次操作可以实现“共同富裕”,即数组中所有元素都相等。

例如对于[1, 1, 1, 2, 3]经过3步:[1, 1, 1, 2, 3] -> [2, 2, 2, 3, 3] -> [3, 3, 3, 3, 4] -> [4, 4, 4, 4, 4]。

输入

第一行包含一个整数N。(1 ≤ N ≤ 100000)
以下N行包含N个整数A1, A2, … AN。 (1 ≤ Ai ≤ 100000)

输出

最小的操作数

样例输入

5
1
1
1
2
3

样例输出

3

GCC
#include <stdio.h>
#include <stdlib.h>
const int MAXN = 100000 + 10; 
int num[MAXN]; 
int comp(const void *a, const void *b){
	return (*(int *)a - *(int *)b); //由小到大排序,return *(int *)b - *(int *)a; 为由大到小排序
}

int main(int argc, char** argv) 
{
	int n;

while (scanf("%d", &n) != EOF)/*EOF:EOF是一个计算机术语,为End Of File的缩写,在操作系统中表示资料源无更多的资料可读取。资料源通常称为档案或串流。通常在文本的最后存在此字符表示资料结束。*/

	{
	 for(int i=0;i<n;i++)
	   {
	       scanf("%d",&num[i]);
	   }
	 qsort(num,n,sizeof(num[0]),comp);//数列由大到小排列 
	 long long ans = 0; 
	 for(int i=n-1; i>0; --i)
		{
			ans += num[i] - num[0]; 
		}
	

	printf("%lld\n", ans ); 
	} 

	return 0;

} 
#include <cstdio> 
#include <cstdlib> 

const int MAXN = 100000; 

int num[MAXN]; 

int cmp(const void *a, const void *b){
	return (*(int *)a - *(int *)b); 
}

int main(){ 
	
	int n; 
	while(scanf("%d", &n) != EOF){ 
		for(int i=0; i<n; ++i){
			scanf("%d", &num[i]);  
		}
		qsort(num, n, sizeof(num[0]), cmp); 
		long long ans = 0; 
		for(int i=n-1; i>0; --i){
			ans += num[i] - num[0]; 
		}
		printf("%lld\n", ans ); 
	} 
	return 0; 
}

EOF 函数编辑
返回一个数值(整数类型Integer),它包含布尔值Boolean值True,表明已经到达为Random(Open语句方法)或顺序Input (Open 语句方法)打开的文件的结尾。
语法
EOF(filenumber)
必要的filenumber参数是一个Integer,包含任何有效的文件号。
说明
EOF (End Of File)
使用EOF是为了避免因试图在文件结尾处进行输入而产生的错误。
直到到达文件的结尾,EOF函数都返回False。对于为访问Random或Binary而打开的文件,直到最后一次执行的Get语句无法读出完整的记录时,EOF都返回False。
贪心算法转自此处 详情点击了解
一、概念

  1. 贪心法(Greedy Algorithm)定义

求解最优化问题的算法通常需要经过一系列的步骤,在每个步骤都面临多种选择;

贪心法就是这样的算法:它在每个决策点作出在当时看来最佳的选择,即总是遵循某种规则,做出局部最优的选择,以推导出全局最优解(局部最优解->全局最优解)

  1. 对贪心法的深入理解

    (1)原理:一种启发式策略,在每个决策点作出在当时看来最佳的选择

    (2)求解最优化问题的两个关键要素:贪心选择性质+最优子结构

    ①贪心选择性质:进行选择时,直接做出在当前问题中看来最优的选择,而不必考虑子问题的解;

    ②最优子结构:如果一个问题的最优解包含其子问题的最优解,则称此问题具有最优子结构性质

    (3)解题关键:贪心策略的选择

    贪心算法不是对所有问题都能得到整体最优解的,因此选择的贪心策略必须具备无后效性,即某个状态以前的过程不会影响以后的状态,只与当前状态有关。

    (4)一般步骤:

    ①建立数学模型来描述最优化问题;

    ②把求解的最优化问题转化为这样的形式:对其做出一次选择后,只剩下一个子问题需要求解;

    ③证明做出贪心选择后:
    1°原问题总是存在全局最优解,即贪心选择始终安全;

    2°剩余子问题的局部最优解与贪心选择组合,即可得到原问题的全局最优解。
    并完成2°

  2. 贪心法与动态规划

     最优解问题大部分都可以拆分成一个个的子问题,
     把解空间的遍历视作对子问题树的遍历,
     则以某种形式对树整个的遍历一遍就可以求出最优解,
     大部分情况下这是不可行的。
     贪心算法和动态规划本质上是对子问题树的一种修剪,
     两种算法要求问题都具有的一个性质就是子问题最优性
     (组成最优解的每一个子问题的解,对于这个子问题本身肯定也是最优的)。
     动态规划方法代表了这一类问题的一般解法,
     我们自底向上构造子问题的解,对每一个子树的根,
     求出下面每一个叶子的值,并且以其中的最优值作为自身的值,
     其它的值舍弃。
     而贪心算法是动态规划方法的一个特例,
     可以证明每一个子树的根的值不取决于下面叶子的值,
     而只取决于当前问题的状况。
     换句话说,不需要知道一个节点所有子树的情况,
     就可以求出这个节点的值。
     由于贪心算法的这个特性,
     它对解空间树的遍历不需要自底向上,
     而只需要自根开始,选择最优的路,
     一直走到底就可以了。
    

对于这道题
思路
1.排序
2.稳定最大的数,其他数增加

1 1 1 2 3
2 2 2 3 3
3 3 3 3 4
4 4 4 4 4
需要三步就可以完成了
1 2 3 4 5
2 3 4 5 5
3 4 5 6 5
4 5 6 6 6
5 6 7 6 7
6 7 8 7 7
7 8 8 8 8
8 9 9 9 8
9 10 10 9 9
10 11 10 10 10
11 11 11 11 11
需要10步
最后一位5稳定了4次 =5-1
倒数第二位4稳定了3次=4-1
倒数第三位3稳定了2次=3-1
倒数第四位2稳定了1次=2-1
所以得出了一个结论
操作数=(a[n]-a[0])+(a[n-1]-a[0])+…+(a[1]-a[0])

qsort

中文名qsort
头文件stdlib.h
用 法voidqsort(void *base,int nelem,int width,int (*fcmp)(constvoid *,const void *));
参数数组首地址 ,数组中待排序元素数量,各元素的占用空间大小,指向函数的指针,用于确定排序的顺序

用法
使用qsort()排序并用 bsearch()搜索是一个比较常用的组合,使用方便快捷。

qsort 的函数原型是

voidQuickSort(int a[],int numsize)//a是整形数组,numsize是元素个数
{
	int i=0,j=numsize-1;
	int val=a[0];//指定参考值val大小
	if(numsize>1)//确保数组长度至少为2,否则无需排序
	{
		while(i<j)//循环结束条件
		{
		for(;j>i;j--)//从后向前搜索比val小的元素,找到后填到a[i]中并跳出循环
			if(a[j]<val)
			{
			a[i]=a[j];
			break;
			}
		for(;i<j;i++)//从前往后搜索比val大的元素,找到后填到a[j]中并跳出循环
			if(a[i]>val)
			{
				a[j]=a[i];
				break;
			}
		}
		a[i]=val;//将保存在val中的数放到a[i]中
		QuickSort(a,i);//递归,对前i个数排序
		QuickSort(a+i+1,numsize-1-i);//对i+1到numsize这numsize-1-i个数排序
	}
}

其中base是排序的一个集合数组,num是这个数组元素的个数,width是一个元素的大小,comp是一个比较函数。

比如:对一个长为1000的数组进行排序时,int a[1000]; 那么base应为a,num应为 1000,width应为 sizeof(int),comp函数随自己的命名。

qsort(a,1000,sizeof(int),comp);

其中comp函数应写为:

int comp(const void *a, const void *b)
{
	return (*(int *)a - *(int *)b); //由小到大排序,return *(int *)b - *(int *)a; 为由大到小排序
}

上面是由小到大排序,return *(int *)b - *(int *)a; 为由大到小排序。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值