合唱团--动态规划

题目描述
有 n 个学生站成一排,每个学生有一个能力值,牛牛想从这 n 个学生中按照顺序选取 k 名学生,
要求相邻两个学生的位置编号的差不超过 d,使得这 k 个学生的能力值的乘积最大,你能返回最大
的乘积吗? 输入描述: 每个输入包含
1 个测试用例。每个测试数据的第一行包含一个整数 n (1 <= n <= 50),表示学
生的个数,接下来的一行,包含 n 个整数,按顺序表示每个学生的能力值 ai(-50 <= ai <= 50
。接下来的一行包含两个整数,k 和 d (1 <= k <= 10, 1 <= d <= 50)。

此考察的是动态规划问题,C++代码如下

/*!
 * \file test.cpp
 * \date 2018/02/07 15:37
 *
 * \author sunicey
 * Contact: sunicey@happy.com
 *
 * \brief 动态规划
 *
 * TODO: 动态规划处理合唱问题
 *
 * \note
*/


//导入头文件
#include <iostream>
#include <vector>
#include <algorithm>

using namespace std;

int main() {

    //input the number of pepole
    int n;
    cin >> n;
    //创建一个容器来存储权值
    vector<long long> a(n + 1);
    //顺序输入权值
    for (int i = 1;i <= n;i++) {
        cin >> a[i];
    }
    //输入合唱的人数以及相邻间隔的差值
    int k, d;
    cin >> k >> d;
    //创建两个二维容器来存储相对应的最大值以及最小值
    //如max_weight[i][j]表示总人数的第i个人作为被挑选的第j人
    vector<vector<long long> > max_weight(n + 1, vector<long long>(k + 1, 0));
    vector<vector<long long> > min_weight(n + 1, vector<long long>(k + 1, 0));
    //设一最小值
    long long res = LLONG_MIN;
    //开始处理,需要建立三层循环,也可以两层循环
    for (int i = 1;i <= n;i++) {
        max_weight[i][1] = min_weight[i][1] = a[i];
        //代表第i个人可被挑选的第j个人,此时必须要求i>=j
        for (int j = 2;j <= k && j <= i;j++) {
            //此时处理相邻被挑选的人不能超过d
            for (int s = 1;s <= d && i - s >= 1;s++) {
                max_weight[i][j] = max(max_weight[i][j], max(max_weight[i - s][j - 1] * a[i], min_weight[i - s][j - 1] * a[i]));
                min_weight[i][j] = min(min_weight[i][j], min(max_weight[i - s][j - 1] * a[i], min_weight[i - s][j - 1] * a[i]));
            }
        }
        res = max(res, max_weight[i][k]);
    }

    for (int i = 1;i <= n;i++) {
        for (int j = 1;j <= k;j++) {
            cout << max_weight[i][j] << " ";
        }
        cout << endl;
    }
    cout << res << endl;
    system("pause");
    return 0;
}

如下测试输出:

 python代码

n = int(input())
arr = map(int,input().split())
k,d = map(int,input().split())
arr = list(arr)
fm = [([0]*k) for i in range(n)]
fn = [([0]*k) for i in range(n)]
res=0
for i in range(0,n):#the ith 0~n-1
    fm[i][0] = arr[i]
    fn[i][0] = arr[i] 
    for j in range(1,min(i,k)):
        for s in range(1,min(d+1,i)):
            fm[i][j] = max(fm[i][j],max(fm[i-s][j-1]*arr[i],fn[i-s][j-1]*arr[i]))
            fn[i][j] = min(fn[i][j],min(fm[i-s][j-1]*arr[i],fn[i-s][j-1]*arr[i]))
    res=max(res,fm[i][k-1])
        
print (res)

 

posted @ 2018-02-07 16:20  mysunicey  阅读(180)  评论(0编辑  收藏  举报