1. 程式人生 > >藍橋杯 演算法提高 ADV-15 最大乘積

藍橋杯 演算法提高 ADV-15 最大乘積

演算法提高 最大乘積
時間限制:1.0s 記憶體限制:512.0MB
問題描述
  對於n個數,從中取出m個數,如何取使得這m個數的乘積最大呢?
輸入格式
  第一行一個數表示資料組數
  每組輸入資料共2行:
  第1行給出總共的數字的個數n和要取的數的個數m,1<=n<=m<=15,
  第2行依次給出這n個數,其中每個數字的範圍滿足:a[i]的絕對值小於等於4。
輸出格式
  每組資料輸出1行,為最大的乘積。
樣例輸入
1
5 5
1 2 3 4 2
樣例輸出
48

分析:這個題不難,直接貪心就好了。值得注意的是,兩個負數的乘積

兩個正數乘積的情況,結果要取兩個負數的積。否則先取一個最大的正數即可。具體操作見註釋,程式碼如下:

#include <iostream>
#include <algorithm>
using namespace std;

int map(int a, int b)
{
	return a > b;
}

int main()
{
	int num;
	int n, m;
	int *a;
	int l, r;
	int res;
	//第一行一個數表示資料組數
	cin >> num;
	//每組輸入資料共2行:
	while(num--)
	{
		//第1行給出總共的數字的個數n和要取的數的個數m,1<=n<=m<=15,
		cin >> n >> m;
		a = new int[n];
		//第2行依次給出這n個數,其中每個數字的範圍滿足:a[i]的絕對值小於等於4。
		for(int j = 0; j < n; j++) cin >> a[j];
		//為陣列從大到小排序
		sort(a, a + n, map);
		//左右端指標l,r以及最終結果res的初始化
		l = 0, r = n - 1, res = 1;
		//取m個數
		while(m > 0)
		{
			if(m >= 2) 
			{
				int left = a[l] * a[l+1]; 
				int right = a[r] * a[r-1];
				
				if(left <= right)	//如果右端乘積比左端大,說明是兩個負數,取他們的積 
				{
					res *= right;
					r -= 2;
					m -= 2;
				}
				else				//否則取最大的正數 
				{
					res *= a[l];
					l++;
					m--;
				}
			}
			else					//最後一個只能取較大的數 
			{
				res *= a[l];
				l++;
				m--; 
			}
		}
		
		cout << res << endl;		//輸出結果 
		delete a;
	}
	
	return 0;
}