798 -> 536 公司合并算法设计

7 篇文章 0 订阅
Problem Statement
    
Warning: This problem statement contains superscripts and/or subscripts. It may not display properly outside of the applet.
 The candy industry is going through a hard time in Byteland. Some of the biggest companies in the business have decided to perform a series of mergers so as to become one company in the end. Due to the depression, each merger should join at least k companies at once. Surprisingly, empirical studies conducted by the economists of Byteland have shown that the revenue of a company that is created by simultainously merging m (m >= k) companies with revenues equal to r0, r1, ..., rm - 1 is equal to the average of these revenues, that is (r0 + r1 + ... + rm - 1) / m.  You are given a int[] revenues. The revenue of the i-th of the companies that want to merge is equal to revenues[i]. Return the maximum possible revenue of the final company that can be created in any series of mergers that joins all the companies.
Definition
    
Class:
MergersDivTwo
Method:
findMaximum
Parameters:
int[], int
Returns:
double
Method signature:
double findMaximum(int[] revenues, int k)
(be sure your method is public)
    


Notes
-
The returned value must have an absolute or relative error less than 10-9.
-
Please note that the revenue of a company may be negative; this means that the company is actually losing money.
-
It is always possible to merge all companies into a single one: for example, by merging all of them in a single step.
Constraints
-
revenues will contain between 2 and 50 elements, inclusive.
-
Each element of revenues will be between -1,000 and 1,000, inclusive.
-
k will be between 2 and the number of elements in revenues, inclusive.
Examples
0)


    
{5, -7, 3}
2
Returns: 1.5
The optimal way is to first merge companies 1 and 2, obtaining a company with total revenue -2, and then merge that company with company 0.
1)


    
{5, -7, 3}
3
Returns: 0.3333333333333333
The respective revenues are the same as in the previous example, but because k = 3, we have to merge all companies at once.
2)


    
{1, 2, 2, 3, -10, 7}
3
Returns: 2.9166666666666665
The solution is to first merge companies 0, 1, 2 and 4, and then merge the resulting company with companies 3 and 5.
3)


    
{-100, -100, -100, -100, -100, 100}
4
Returns: -66.66666666666667
Note that we can't merge less than six companies in the first step, because otherwise we would be left with only two or three companies and we would be unable to finish the merging process.
4)


    
{869, 857, -938, -290, 79, -901, 32, -907, 256, -167, 510, -965, -826, 808, 890,
 -233, -881, 255, -709, 506, 334, -184, 726, -406, 204, -912, 325, -445, 440, -368}
7

Returns: 706.0369290573373


递归算法

#include <vector>
#include <algorithm>
#include <functional>
#include <numeric>
using namespace std;


class MergersDivTwo
{
public:
	double findMaximum( vector<int> revenues, int k )
	{
		sort( revenues.begin(), revenues.end() );
		maxCach.insert( maxCach.begin(), revenues.size(), 0 );
		maxCalculated.insert( maxCalculated.begin(), revenues.size(), false );
		return maxRecursive( revenues, revenues.size(), k );
	}
private:
	vector<double> maxCach;
	vector<bool> maxCalculated;
	// assume revenues are sorted
	double maxRecursive( vector<int>& revenues, int end, int k )
	{
		// can not be divided
		if( maxCalculated[end]  ) return maxCach[end] ;
		double sum = (double) accumulate( revenues.begin(), revenues.begin() + end, 0 ) / (double) end;
		if( k * 2 - 1 > end )
		{
			maxCalculated[end] = true;
			maxCach[end] = sum;
			return sum;
		}
		int halfCount = (end + 1) / 2;
		double max = sum;
		for( int idx = k - 1; idx <= halfCount; idx++ )
		{	
			double tempSum = accumulate( revenues.begin() + end - idx, revenues.begin() + end, 0 );
			double tempMax = (double)(maxRecursive( revenues, end - idx, k ) + tempSum) / (double)(idx + 1);
			if( tempMax > max )	max = tempMax;
		}
		return max;
	}
};


循环算法

#include <vector>
#include <algorithm>
#include <functional>
#include <numeric>
using namespace std;


class MergersDivTwo
{
public:
	double findMaximum( vector<int> revenues, int k )
	{
		sort( revenues.begin(), revenues.end() );	
		vector<double> maxRevenues;
		for( int count = k; count <= revenues.size(); count++ )
		{
			double sum = (double) accumulate( revenues.begin(), revenues.begin() + count, 0 ) / (double) count;
			if( k * 2 - 1 > count ) 
			{
				maxRevenues.push_back( sum );
			}
			else
			{	
				int halfCount = count / 2;
				for( int idx = k - 1; idx <= halfCount; idx++ )
				{			
					double tempSumNotDivided = accumulate( revenues.begin() + count - idx, revenues.begin() + count, 0 );
					double tempMax = (double) (maxRevenues[ count - idx - k ] + tempSumNotDivided) / (double) (idx + 1);
					if( tempMax > sum ) sum = tempMax;
				}
				maxRevenues.push_back( sum );
			}
		}
		return( maxRevenues[ revenues.size() - k] );
	}
};



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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值