POJ 3399 - Product
http://poj.org/problem?id=3399
概要
N 個の整数が与えられる. この中から積が最大になるような K 個の数字を出力する.
積を最大にするような K 個の選び方が複数ある場合は,どれを出力しても構わない.
制約
- 1 <= K <= N <= 100
- -30000 <= 要素の値 <= 30000
- 単調非増加列となるように答えを出力する
解法
まず例外ケースとして,非負整数が1つも無く K が奇数の場合,どのように選んでも積は負になる. よって,このときは大きい方から K 個選んだときに積が最大になる.
そうでない場合は,うまく K 個選べば積を非負にすることができる.
まず入力を非負と負に分け,それぞれ絶対値に関して大きい順にソートしておく.
K が偶数のとき,非負の上2つの積と負の上2つの積を比べ,大きい方から2つずつ貪欲に選んでいけば最適になる.
一方 K が奇数のときは,必ず1つは非負整数を選ばないと積が非負にならないので,最大の非負整数を最初に選んでから,K-1 で上の手順をすればよい.
poj/3399.cc1 #include <iostream> 2 #include <vector> 3 #include <deque> 4 #include <algorithm> 5 using namespace std; 6 7 int main() 8 { 9 int N, K; 10 cin >> N >> K; 11 deque<int> pos, neg; 12 for (int i = 0; i < N; i++) { 13 int x; 14 cin >> x; 15 if (x >= 0) { 16 pos.push_back(x); 17 } else { 18 neg.push_back(-x); 19 } 20 } 21 if (K % 2 == 1 && pos.empty()) { 22 sort(neg.begin(), neg.end()); 23 for (int i = 0; i < K; i++) { 24 if (i != 0) { 25 cout << " "; 26 } 27 cout << -neg[i]; 28 } 29 cout << endl; 30 return 0; 31 } 32 33 sort(pos.rbegin(), pos.rend()); 34 sort(neg.rbegin(), neg.rend()); 35 36 vector<int> ans; 37 if (K % 2 == 1) { 38 ans.push_back(pos[0]); 39 pos.pop_front(); 40 K--; 41 } 42 for (; K > 0; K -= 2) { 43 if (pos.size() < 2) { 44 ans.push_back(-neg[0]); 45 ans.push_back(-neg[1]); 46 neg.pop_front(); 47 neg.pop_front(); 48 } else if (neg.size() < 2) { 49 ans.push_back(pos[0]); 50 ans.push_back(pos[1]); 51 pos.pop_front(); 52 pos.pop_front(); 53 } else { 54 const int p = pos[0] * pos[1]; 55 const int n = neg[0] * neg[1]; 56 if (p >= n) { 57 ans.push_back(pos[0]); 58 ans.push_back(pos[1]); 59 pos.pop_front(); 60 pos.pop_front(); 61 } else { 62 ans.push_back(-neg[0]); 63 ans.push_back(-neg[1]); 64 neg.pop_front(); 65 neg.pop_front(); 66 } 67 } 68 } 69 70 sort(ans.rbegin(), ans.rend()); 71 for (vector<int>::const_iterator it = ans.begin(); it != ans.end(); ++it) { 72 if (it != ans.begin()) { 73 cout << " "; 74 } 75 cout << *it; 76 } 77 cout << endl; 78 return 0; 79 }