【贪心】数列极差问题

题目描述

“我就说你在忽悠我吧,我刚才问了昆士兰大学的好多魔法师,他们根本就没有一个人想过做什么时间旅行的实验,但搞笑的是,他们居然对你的理论很感兴趣,想找个时间和你做进一步的讨论。哎,我还以为他们和我一样聪明呢,想不到这么容易上当受骗。”小墨老师摆出一幅你骗不了我的表情。

“唉,你太自以为是了,这样吧,你先把这道数列极差问题发给他们,如果他们能有所领悟,那我会找时间和他们讨论一下时间旅行的可行性的。”李旭琳边说边在黑板上写了N个正整数组成的一个数列,并进行如下操作:每次擦去其中的两个数a和b,然后在数列中加入一个数a×b+1,如此下去直至黑板上剩下一个数,在所有按这种操作方式最后得到的数中,最大的为max,最小的为min,则该数列的极差定义为M=max-min。

现在请你编程,对于给定的数列,计算极差。

输入

输入包含多个测试集。每个测试集的第一个数N表示 正整数序列长度(0≤N≤50000),随后是N个正整数。N为0表示输入结束。

输出

每个结果一行。

样例输入

3
1 2 3
0

样例输出

2

首先这个题如果拿出几个测试案例来看的话,容易推导出这是一道贪心题,就拿本题的测试案例来看,1 2 3 这三个数有三种不同的操作顺序
1:(1*2+1)*3+1=10

2:(1*3+1)*2+1=9

3:(2*3+1)*1+1=8

从中我们容易发现这样的顺序,如果要求最大值的话,那么每次先用最小的连个数相乘的结果+1,相反,如果要求最小值的话,每次先用最大的两个数相乘的结果+1.这样我们就可以写算法啦

#include<iostream>
#include<algorithm>
using namespace std;
//定义两个数组用于求最大和最小值得时候使用
 int s[50001];
 int j[50001];
 int cmp(int a,int b){
 return a>b;
 }
int main(){
	int n;
	while(cin>>n&&n){
	for(int i=0;i<n;i++){
	cin>>s[i];
	j[i]=s[i];
	}
	//先升序排列
	sort(s,s+n);
	for(int i=1;i<n;i++){
	s[i]=s[i]*s[i-1]+1;//从小到大排完序之后,先从前边最小的两个数相乘然后存放到数组里
	sort(s+i,s+n);/*算法的核心部分,由于每次从最小的两个数相乘后的数值
				  放到原来的数组中有可能会破坏数组从小到大的顺序,所以再用一个sort排序,使新的数组变得有序,
				  依次循环下去,就会得到最大值。*/

	}
	int max=s[n-1];
	//降序排列并求最小值
	sort(j,j+n,cmp);
	for(int i=1;i<n;i++){
	j[i]=j[i-1]*j[i]+1;/*而求最小值的时候就不用sort每次都排序啦,因为前边两个最大的数乘起来
					   的数不可能会比后边小的数还要小,所以求最小值得时候会比上边要简单一些*/
	}
	int min=j[n-1];
cout<<max-min<<endl;
	}
return 0;
}


猜你喜欢

转载自blog.csdn.net/u014788620/article/details/80957983
今日推荐