Problem H
Maximum Subsequence
Input: Standard Input
Output: Standard Output
Time Limit: 2 Second
You are given a sequence of N integers, each of which is not greater than 10,000 considering absolute value. There are (NCK) sub-sequences possible from this sequence. You have to pick such a subsequence, so that multiplication of all its integers is maximum.
For example, if the sequence is 4, 4, -4, -4 and you are asked to pick 2 integers. You have 2 ways, which will satisfy the criterion. One is to pick 4,4 and the other is to pick –4, -4.
In this case, you have to consider the sub sequence whose summation of all integers is maximum.
Input
The input file contains several sets of inputs. The description of each set is given below.
Each input set starts with 2 positive integers N, K (1<=K<=N<=10000). Next N non-empty lines contain N integers in total.
Input is terminated by a case where N=0 and K=0. This case should not be processed. There will be at most 60 test cases.
Output
For each set of input print in a single line the summation of the integers in the desired subsequence.
Sample Input Output for Sample Input
4 4 1 2 3 4 4 1 1 2 3 4 4 2 4 4 –4 –4 0 0 |
10 4 8 |
题意:给定n个数字,中选出k个数字,使得乘积最大,如果有乘积相同的,就要和最大的。
思路:贪心,按数字绝对值从大到小排,相同按正数排前面,从头选k个数字,如果选到0,说明乘积始终为0,那么只要选最大的k个就可以了,如果这些数字负数个数为偶数个,乘积>0是最优,如果为奇数个。则要考虑:去掉一个正数换后面最大的负数,去掉一个负数换后面最大的正数。两种情况比较乘积和总和,不过要注意,如果换到的是0的话要特殊考虑,并且在比较乘积的时候,整个乘积是保存不下来的,注意对于一次替换。sum = sum / m* z。这样只要保存下m和z就可以比较了,细节比较多,写得有点搓。
代码:
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <algorithm>
#define max(a,b) (a)>(b)?(a):(b)
#define INF 0x3f3f3f3f
using namespace std;
const int N = 10005;
int n, k, seq[N];
bool cmp(int a, int b) {
if (abs(a) != abs(b))
return abs(a) > abs(b);
return a > b;
}
void init() {
for (int i = 0; i < n; i++)
scanf("%d", &seq[i]);
}
int solve() {
int sum = 0, fn = 0;
sort(seq, seq + n, cmp);
for (int i = 0; i < k; i++) {
sum += seq[i];
if (seq[i] < 0) fn++;
}
if (fn % 2) {
int sum1 = -INF, sum2 = -INF, m1, z1, m2, z2;
for (int i = k - 1; i >= 0; i--) {
if (sum1 != -INF && sum2 != -INF) break;
if (seq[i] > 0 && sum1 == -INF) {
for (int j = k; j < n; j++) {
if (seq[j] < 0) {
sum1 = sum - seq[i] + seq[j];
m1 = abs(seq[i]); z1 = abs(seq[j]);
break;
}
}
}
else if (seq[i] < 0 && sum2 == -INF) {
for (int j = k; j < n; j++) {
if (seq[j] >= 0) {
sum2 = sum - seq[i] + seq[j];
m2 = abs(seq[i]); z2 = abs(seq[j]);
break;
}
}
}
else if (seq[i] == 0) {
sort(seq, seq + n);
sum = 0;
for (int i = n - 1; i >= n - k; i--)
sum += seq[i];
return sum;
}
}
if (z2 == 0 && sum1 == -INF) {
sort(seq, seq + n);
sum = 0; int flag = 0;
for (int i = n - 1; i > n - k; i--) {
if (seq[i] == 0) flag = 1;
sum += seq[i];
}
if (flag)
sum += seq[n - k];
return sum;
}
if (sum1 == -INF && sum2 == -INF) {
sum = 0; for (int i = n - 1; i >= n - k; i--)
sum += seq[i];
return sum;
}
else if (sum1 == -INF && sum2 != -INF) return sum2;
else if (sum1 != -INF && sum2 == -INF) return sum1;
if (z1 * m2 == z2 * m1) sum = max(sum1, sum2);
else if (z1 * m2 > z2 * m1) sum = sum1;
else sum = sum2;
}
else {
if (seq[k - 1] == 0) {
sort(seq, seq + n);
sum = 0;
for (int i = n - 1; i >= n - k; i--)
sum += seq[i];
}
}
return sum;
}
int main() {
while (~scanf("%d%d", &n, &k) && n + k) {
init();
printf("%d\n", solve());
}
return 0;
}