一天十题选择,一天一道编程,一天一个面试题,一个一个剑指offer
排序是必须要掌握的一个算法,非常的重要
题目描述
有 n 个学生站成一排,每个学生有一个能力值,牛牛想从这 n 个学生中按照顺序选取 k 名学生,要求相邻两个学生的位置编号的差不超过 d,使得这 k 个学生的能力值的乘积最大,你能返回最大的乘积吗?
输入描述:
每个输入包含 1 个测试用例。每个测试数据的第一行包含一个整数 n (1 <= n <= 50),表示学生的个数,接下来的一行,包含 n 个整数,按顺序表示每个学生的能力值 ai(-50 <= ai <= 50)。接下来的一行包含两个整数,k 和 d (1 <= k <= 10, 1 <= d <= 50)。
输出描述:
输出一行表示最大的乘积。
示例1
输入
3
7 4 7
2 50
输出
49
题目分析
本题是网易的一道动态规划的题目,题目中让我们求解的是一个最优解的问题,我们这里可以考虑使用的算法是动态规划来进行求解,这里我们需要求解从n个人当中选择k使得这k的乘积最大,这个问题我们就需要设置的 二维数组,数组的中表示的是第i个数作第j个乘数的时候的最大值,这里我们需要维护一个最大值的数组,还需要维护一个最小值的数组,原因是,我们的最大值可能是由我们的最小值的一个负数乘以一个负数得到的,同时我们的最小值也可能是最大值中的一个最大数乘以我们的一个负数得到的,所以这里需要维护两个数组,同时还应该注意的一个问题就是,我们的数据中,还需要控制的一个间距。
代码
#define _CRT_SECURE_NO_WARNINGS 1
#include<iostream>
#include<vector>
#include<algorithm>
using namespace std;
int main()
{
int n;
while (cin >> n)
{
vector<long long> arr(n);
for (int i = 0; i<n; i++)
{
cin >> arr[i];
}
int k, d;
cin >> k >> d;
vector<vector<long long>> dp_max(n, vector<long long>(k + 1, 0));
vector<vector<long long>> dp_min(n, vector<long long>(k + 1, 0));
//初始化最大和最小数组
for (int i = 0; i<n; i++)
{
dp_max[i][1] = arr[i];
dp_min[i][1] = arr[i];
}
for (int i = 0; i<n; i++)
{
for (int j = 2; j<k + 1; j++)
{
for (int m = max(0, i - d); m<=i - 1; m++) //这里的m控制的是间隔,就是说,我们的间隔要控制好了
{
dp_max[i][j] = max(dp_max[i][j], max(dp_max[m][j - 1] * arr[i], dp_min[m][j - 1] * arr[i]));
dp_min[i][j] = min(dp_min[i][j], min(dp_min[m][j - 1] * arr[i], dp_max[m][j - 1] * arr[i]));
}
}
}
long long maxnum = dp_max[k-1][k];
for (int i = k; i<n; i++)
{
maxnum = max(maxnum, dp_max[i][k]);
}
cout << maxnum << endl;
}
return 0;
}