zoukankan      html  css  js  c++  java
  • 合唱团(动态规划)

    题目: 合唱团

    有 n 个学生站成一排,每个学生有一个能力值,牛牛想从这 n 个学生中按照顺序选取 k 名学生,要求相邻两个学生的位置编号的差不超过 d,使得这 k 个学生的能力值的乘积最大,你能返回最大的乘积吗?

    输入描述

    每个输入包含 1 个测试用例。每个测试数据的第一行包含一个整数 n (1 <= n <= 50),表示学生的个数,接下来的一行,包含 n 个整数,按顺序表示每个学生的能力值 ai(-50 <= ai <= 50)。接下来的一行包含两个整数,k 和 d (1 <= k <= 
    10, 1 <= d <= 50)。

    输出描述

    输出一行表示最大的乘积

    输入例子

    3
    7 4 7
    2 50

    输出例子

     49

    分析

      元素有正有负,要考虑负负得正的情况

      相邻元素间隔不超过d

      使用动态规划,从最后一个元素入手

      fm[k][i]表示以a[i]为最后一个元素,选取k个学生所能达到的最大乘积

      fn[k][i]表示以a[i]为最后一个元素,选取k个学生所能达到的最小乘积

      为了理解方便,我们将行数为0和列数为0的元素都赋值为0不去考虑,可以看作下标从1开始

     

    n = int(raw_input())
    a = raw_input().strip().split()
    a = list(map(int,a))
    a.insert(0,0)
    kd = raw_input().strip().split()
    kd = list(map(int,kd))
    K = kd[0]
    D = kd[1]
    
    fm = [[0]*(n+1) for i in range(K+1)]
    fn = [[0]*(n+1) for i in range(K+1)]
    
    for i in range(1,n+1):
        fm[1][i] = a[i]
        fn[1][i] = a[i]
    res = 0
    for i in range(1,n+1):
        for k in range(2,K+1):
            for j in range(i-1,max(i-D,0)-1,-1):
                fm[k][i] = max(fm[k][i],fm[k-1][j]*a[i],fn[k-1][j]*a[i])
                fn[k][i] = min(fn[k][i],fm[k-1][j]*a[i],fn[k-1][j]*a[i])
        res = max(res,fm[K][i])
    print(res)

     

     

  • 相关阅读:
    tomcat-01-配置文件组成
    Mysql的批量导入
    Mysql优化
    没有处理的问题
    Java 实现一个带提醒的定时器
    Java 端口扫描器 TCP的实现方法
    Java 多态方法构造器执行方法
    JavaWeb 基于Session的用户登陆注销实现
    Java 访问权限控制 小结
    Java FTP下载文件以及编码问题小结
  • 原文地址:https://www.cnblogs.com/Peyton-Li/p/7555072.html
Copyright © 2011-2022 走看看