合唱團 N個學生中選K個,相鄰兩個的位置編號不超過D,使得K個學生乘積最大
阿新 • • 發佈:2018-12-11
網易2016內推筆試題:
有 n 個學生站成一排,每個學生有一個能力值,從這 n 個學生中按照順序選取 k 名學生,要求相鄰兩個學生的位置編號的差不超過 d,使得這 k 個學生的能力值的乘積最大,返回最大的乘積。 每個輸入包含 1 個測試用例。每個測試資料的第一行包含一個整數 n (1 <= n <= 50),表示學生的個數,接下來的一行,包含 n 個整數,按順序表示每個學生的能力值 ai(-50 <= ai <= 50)。接下來的一行包含兩個整數,k 和 d (1 <= k <= 10, 1 <= d <= 50)。
#include<iostream> #include<cstring> #include<algorithm> #include<stack> #include<set> #include<queue> using namespace std; inline long long max(long long a, long long b){ return (a > b) ? a : b; } inline long long min(long long a, long long b){ return (a > b) ? b : a; } int main(int argc, char * argv[]) { int n, *a, k, d; // 選k個學生,位置編號不超過d // 尤其注意, dp_max[i][k] 表示在前 i 個數中選 k 個數,使得乘積最大, 且第 i 個數必選!!!!!! // 同理,dp_max[i][k] 表示在前 i 個數中選 k 個數,使得乘積最小, 且第 i 個數必選!!!!!! long long dp_max[52][12], dp_min[52][12]; while (~scanf("%d", &n)) { /*********** Input ****************/ a = new int[n + 1]; memset(a, 0, sizeof(int)*(n + 1)); for (int i = 0; i < 52;i++) for (int j = 0; j < 12; j++) { dp_max[i][j] = 1; dp_min[i][j] = 1; } for (int i = 1; i <= n; i++) scanf("%d", &a[i]); cin >> k >> d; /*********** Algorithm ****************/ // dynamic programing // initial dp_max[1][1] = dp_min[1][1] = a[1]; for (int i = 1; i <= n; i++) for (int j = 1; j <= k; j++){ // for (int s = 1; s <= d; s++){ if (i - s >= 1){ dp_max[i][j] = max(dp_max[i][j], dp_max[i - s][j - 1] * a[i]); dp_max[i][j] = max(dp_max[i][j], dp_min[i - s][j - 1] * a[i]); dp_min[i][j] = min(dp_min[i][j], dp_min[i - s][j - 1] * a[i]); dp_min[i][j] = min(dp_min[i][j], dp_max[i - s][j - 1] * a[i]); } } } /*********** Output ****************/ long long ans = 0; for (int i = 1; i <= n; i++) ans = max(ans, dp_max[i][k]); printf("%lld\n", ans); } return 0; }