每日一題 -- 11-1

NeilZhy發表於2017-11-01

一天十題選擇,一天一道程式設計,一天一個面試題,一個一個劍指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;
}

相關文章