首页 > 试题广场 >

合唱团

[编程题]合唱团
  • 热度指数:104990 时间限制:C/C++ 1秒,其他语言2秒 空间限制:C/C++ 32M,其他语言64M
  • 算法知识视频讲解
有 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

为啥提示返回非0,我在自己机器上测试都是正常的,后来我用别人已通过代码提交还是报返回非0

def maxP(k, n, d, abilitys):
    if k==0:
        return
    state = [[['N' for _ in range(k)] for _ in range(n)] for _ in range(2)]
    maxp = -float('inf')
    state[0][0][0] = abilitys[0]
    state[1][0][0] = abilitys[0]

    for i in range(1, n):
        state[0][i][0] = abilitys[i]
        state[1][i][0] = abilitys[i]
        for j in range(1, k):
            if state[0][i-1][j-1]=='N':
                break
            mx, mi = -float('inf'), float('inf')
            for w in range(max([0, i-d]), i):
                if state[0][w][j-1]!='N':
                    a = state[0][w][j-1]*abilitys[i]
                    b = state[1][w][j-1]*abilitys[i]
                    if a > b:
                        mx = max([mx, a])
                        mi = min([mi, b])
                    else:
                        mx = max([mx, b])
                        mi = min([mi, a])
                else:
                    break
            state[0][i][j] = mx
            state[1][i][j] = mi
        if state[0][i][j] != 'N' and state[0][i][j] > maxp:
            maxp = state[0][i][j]

    return maxp
a = int(input())
b = list(map(int, input().split()))
c = list(map(int, input().split()))
print(maxP(c[0], a, c[1], b))
发表于 2020-10-08 10:16:20 回复(0)

动态规划:构建动态规划矩阵,横坐标为students,纵坐标为选择人数,每个值[x,y]代表以students[y]结尾的最大值或最小值(即选择的学生中一定有最后一个学生)。因为包含负数,所以需要构建两个动态规划矩阵fm与fn,一个表示最大值一个表示最小值,这样每次更新乘以最后一个students时选择最大的为fm更新值,最小的为fn更新值。如果没有d的限制,则fm[x+1][y+1]=max(fm[x][y]students[y+1],fn[x][y]students[y+1]),fn[x+1][y+1]=min(fm[x][y]students[y+1],fn[x][y]students[y+1])。因为本题有d的限制,所以需要遍历d,求max(fm[x][y-z]students[y+1],fn[x][y-z]students[y+1])所有解中的最大值与min(fm[x][y-z]students[y+1],fn[x][y-z]students[y+1])所有解中的最小值。 矩阵初始化见代码。

import sys
def s(students,a):
    sol = 1
    for i in range(a+1):
        sol*=students[i]
    return sol
n = sys.stdin.readline().strip()
n = int(n)
students = sys.stdin.readline().strip()
students = list(map(int, students.split()))
k, d =map(int, sys.stdin.readline().strip().split())
fm =[["0"]*n for i in range(k)]
fn =[["0"]*n for i in range(k)]
sol_max=[]
sol_min=[]
for i in range(k):
    for j in range(n):
        if i>j:
            fm[i][j]=0
            fn[i][j]=0
        elif i == j :
            fm[i][j]=s(students,i)
            fn[i][j]=s(students,i)
        elif i ==0:
            fm[i][j] =students[j]
            fn[i][j] =students[j]
for x in range(k-1):
    for y in range(x+1,n-1):
        Max = -100000000
        Min = 100000000
        for z in range(d):
            if y-z<0:
                break
            if max(fm[x][y-z]*students[y+1],fn[x][y-z]*students[y+1])>Max:
                Max = max(fm[x][y-z]*students[y+1],fn[x][y-z]*students[y+1])
            if min(fm[x][y-z]*students[y+1],fn[x][y-z]*students[y+1])<Min:
                Min = min(fm[x][y-z]*students[y+1],fn[x][y-z]*students[y+1])
        fm[x+1][y+1]=max(Max,Min)
        fn[x+1][y+1]=min(Max,Min)

for i in range(k):
    sol_max.append(max(fm[i]))
    sol_min.append(min(fn[i]))
print(max(sol_max))


```

编辑于 2019-04-05 11:00:05 回复(0)
arr_len = int (input().strip())
arr = list(map(int,input().strip().split()))
arr2 = list(map(int,input().strip().split()))
K = arr2[0]
D = arr2[1]
max_list = []
min_list = []
empty_list = [0]*arr_len for i in range(K):  max_list.append(empty_list.copy())
    min_list.append(empty_list.copy()) for elem_index in range(arr_len):  max_list[0][elem_index] = arr[elem_index]
    min_list[0][elem_index] = arr[elem_index]
    max_No = min(elem_index,K-1) for No in range(1,max_No+1):  start_index = max(elem_index - D,No-1) if arr[elem_index]>0:  max_list[No][elem_index] = max(max_list[No-1][start_index:elem_index]) * arr[elem_index]
            min_list[No][elem_index] = min(min_list[No-1][start_index:elem_index]) * arr[elem_index] else:  max_list[No][elem_index] = min(min_list[No-1][start_index:elem_index]) * arr[elem_index]
            min_list[No][elem_index] = max(max_list[No-1][start_index:elem_index]) * arr[elem_index] print(max(max_list[K-1][K-1:]))
动态求原数组中每个元素arr[elem_index]作为结果列表的第N个元素时,当前的最大和最小结果。
维护两个最大最小列表max_list[N][elem_index] 和min_list[N][elem_index]。
此列表的值与max_list[N-1] 和min_list[N-1]动态相关。

发表于 2019-01-03 17:37:46 回复(0)
python 先选择满足要求的排列组合,在计算成绩找出最大值
# -*- coding:utf-8 -*-  import itertools def chooseD(n,k,d):
    D = [] #n中选k个,位置编号差值不超过d,满足的编号组合  s = ""  for i in range(n):
        s += str(i) for item in itertools.combinations(s, k):
        item = [int(t) for t in item]
        dd = 1 #相邻元素位置差值小于d的标志,0不满足,1满足  for i in range(len(item)-1): if item[i+1] - item[i] >= d:
                dd = 0  break  if dd == 1:
            D.append(item) return D def MultiplyD(list1,list2):
    result = 1 #返回list1 按照组合list2相乘的乘积  for i in range(len(list2)):
        result *= list1[list2[i]] return result
n = int(input())
ai = list(map(int,input().split()))
k, d = input().split()
D = chooseD(n,int(k),int(d)) for i in range(len(D)): if i == 0:
        max_result = MultiplyD(ai,D[i]) else:
        max_result = max(max_result,MultiplyD(ai, D[i])) print(max_result)
您的代码已保存
答案错误:您提交的程序没有通过所有的测试用例
case通过率为20.00%

测试用例:
36
7 -15 31 49 -44 35 44 -47 -23 15 -11 10 -21 10 -13 0 -20 -36 22 -13 -39 -39 -31 -13 -27 -43 -6 40 5 -47 35 -8 24 -31 -24 -1 
3 31

对应输出应该为:

108241

你的输出为:

117649

只通过20%?  神奇
发表于 2018-09-25 17:37:58 回复(0)

参考各位大佬的解答如:bupt渣硕,加深自己对动态规划问题的理解,附上代码和理解注释

N = int(raw_input())
A = map(int, raw_input().split())
K, D = map(int, raw_input().split())
#因为有正反所以分成两部分
dpmax = [[0]*N for i in range(K)]#列出未来将要用到的结果位置
dpmin = [[0]*N for i in range(K)]#同上
res = (1<<64)*-1#默认的最小值,后面比较需要
for n in range(N):
    dpmax[0][n] = dpmin[0][n] = A[n]#就是在k=1时,取第一个值时
    for k in range(1,K):
        for pre in range(max(0,n-D),n):#因为有间隔,所以如果间隔大于n,可以全取,反之需从间隔部分之后开始
            dpmax[k][n] = max(dpmax[k][n],max(dpmax[k-1][pre]*A[n],dpmin[k-1][pre]*A[n]))#不断与之前的进行比较获取最大
            dpmin[k][n] = min(dpmin[k][n],min(dpmax[k-1][pre]*A[n],dpmin[k-1][pre]*A[n]))#不断与之前进行比较获取最小
    res = max(res,dpmax[K-1][n])
    #其实结果可以写成max([x for x in dpmax[K-1]]))
    #因为是要在dpmax[K-1]取出最大的那个
print(max([x for x in dpmax[K-1]])))

动态规划问题差不多一次看见,得多找一些练习一下୧(๑•̀⌄•́๑)૭

发表于 2018-09-23 14:48:59 回复(1)

思路

设dpMax = [[1 for i in range(k+1)] for j in range(n+1)] 表示以第i个人为最后一个人,一共选取了j个人时的最大乘积。 同理,dpMin = [[1 for i in range(k+1)] for j in range(n+1)] 表示同样状态下的最小乘积(由于数据中存在负数,负数乘上某个极大的负数反而会变成正的极大值,因而需要同时记录最小值)。 dpMax[i][j] 很显然与dpMax[p][j-1] (for p in range(max(i-d, 0), i)表示遍历当前数之前符合范围条件的所有数, 而 j-1则表示所有数中每一个数对应的只比当前乘积因子数少一个时的结果)相关,可以理解为dpMax[i][j]由两部分组成,一部分是自身作为待选值,另一部分是dpMax[p][j-1]乘上一个人后得到的值,然后取它们的极大值,由此可以得到状态转移方程如下: dpMax[i][j] = max(dpMax[i][j], max(dpMax[p][j-1]array[i-1], dpMin[p][j-1]array[i-1])) dpMin[i][j] = min(dpMin[i][j], min(dpMax[p][j-1]array[i-1], dpMin[p][j-1]array[i-1]))

n = int(input()) array = [int(x) for x in input().split()] k, d =[int(x) for x in input().split()] dpMax = [[1 for i in range(k+1)] for j in range(n+1)] dpMin = [[1 for i in range(k+1)] for j in range(n+1)] result = 0 for i in range(1, n+1): for j in range(1, k+1): for p in range(max(i-d, 0), i): dpMax[i][j] = max(dpMax[i][j], max(dpMax[p][j-1]*array[i-1], dpMin[p][j-1]*array[i-1])) dpMin[i][j] = min(dpMin[i][j], min(dpMax[p][j-1]*array[i-1], dpMin[p][j-1]*array[i-1])) if dpMax[i][j] > result: result = dpMax[i][j] print(result)

编辑于 2018-09-08 10:40:28 回复(1)
import sys

n = int(sys.stdin.readline().strip())
students = [int(i) for i in sys.stdin.readline().strip().split()]
k, d = [int(i) for i in sys.stdin.readline().strip().split()]

dp = [[[0,0] for i in range(n)] for j in range(k)]
for j in range(n):
    dp[0][j] = [students[j], students[j]]

for i in range(1, k):
    for j in range(n):
        if j >= i:
            maxi = dp[i-1][max(j-d,0)][0]*students[j]
            mini = dp[i-1][max(j-d,0)][1]*students[j]
            for m in range(max(j-d,0), j):
                temp_maxi = dp[i-1][m][0]*students[j]
                temp_mini = dp[i-1][m][1]*students[j]
                tma = max(temp_maxi, temp_mini)
                tmi = min(temp_maxi, temp_mini)
                if tma > maxi:
                    maxi = tma
                if tmi < mini:
                    mini = tmi
            dp[i][j][0] = maxi
            dp[i][j][1] = mini


maxi = 0
for j in range(n):
    if dp[k-1][j][0] >= maxi:
        maxi = dp[-1][j][0]
print(maxi)

发表于 2018-08-11 14:04:31 回复(0)
0. 每一个状态只与前一个状态有关
1. 前一个状态是一个范围,前D个之内的一个
2. 有正负所以需要维护两个表
N = int(raw_input().strip())
ab = map(int, raw_input().strip().split(' '))
(K, D) = map(int, raw_input().strip().split(' '))

dmax = [[0] * N for i in range(K)]
dmin = [[0] * N for i in range(K)]
res = (1 << 64) * -1

for i in range(N):
    dmax[0][i] = dmin[0][i] = ab[i] \
    for k in range(1, K):
        for pre in range(max(0, i - D), i):
            dmax[k][i] = max(dmax[k][i],
                max(dmax[k - 1][pre] * ab[i],dmin[k - 1][pre] * ab[i]))
            dmin[k][i] = min(dmin[k][i],    min(dmax[k - 1][pre] * ab[i], dmin[k - 1][pre] * ab[i]))
    res = max(res, dmax[K - 1][i])

print res


编辑于 2018-03-06 18:50:41 回复(0)
n = int(raw_input())
student = [int(x) for x in raw_input().split()]
k, d = [int(x) for x in raw_input().split()]

res_max = [[0]*k for i in range(n)]
res_min = [[0]*k for i in range(n)]

for i in range(n):
    res_max[i][0] = student[i]
    res_min[i][0] = student[i]

for j in range(1, k):
    for i in range(n):
        for p in range(i+1, min(i+d+1, n)):
            res_max[p][j] = max(max(res_min[i][j-1]*student[p], res_max[i][j-1]*student[p]), res_max[p][j])
            res_min[p][j] = min(min(res_min[i][j-1]*student[p], res_max[i][j-1]*student[p]), res_min[p][j])

print(max(res_max[i][k-1] for i in range(n)))
# res[i][j]表示前i个人中选j个人的最大值/最小值,第j个选择必须是i

编辑于 2018-02-28 00:43:28 回复(0)
#python2 时间:35ms,内存:3060k 动态规划
length = input()
array = [int(x) for x in raw_input().split()]
k ,d =[int(x) for x in raw_input().split()]
array_max=array_min=array
for i in range(k-1):
    new_max = [-float('inf')]*length
    new_min = [float('inf')]*length
    for num in range(i+1,length):
        index_min = max(i,num-d)
        index_max = min(num+d,length)
        temp_max = -float('inf')
        temp_min = float('inf')
        for temp in range(index_min,num):
            temp_max = max(temp_max,array[num]*array_max[temp],array[num]*array_min[temp])
            temp_min = min(temp_min,array[num]*array_max[temp],array[num]*array_min[temp])
        new_max[num]=temp_max
        new_min[num]=temp_min
    array_max = new_max[:]
    array_min = new_min[:]
print(max(array_max))

发表于 2017-10-21 18:41:03 回复(0)
#coding=utf-8 n=input()
a=list(raw_input().split())
a=[int(i) for i in a]
ik,d=raw_input().split()
ik=int(ik)
d=int(d) #动态规划,用两个数组,保留一正一负两个结果 mx=[[0 for i in range(n)] for i in range(ik)]
mn=[[0 for i in range(n)] for i in range(ik)]
m=0 for i in range(n):
   mx[0][i]=mn[0][i]=a[i] for k in range(1,ik): for j in range(i-1,-1,-1): if i-j>d: break  mx[k][i]=max(mx[k][i],max(mx[k-1][j]*a[i],mn[k-1][j]*a[i]))
         mn[k][i]=min(mn[k][i],min(mx[k-1][j]*a[i],mn[k-1][j]*a[i]))
   m=max(m,mx[ik-1][i]) print m

发表于 2017-08-10 14:21:10 回复(0)
没有用动态规划。使用的是递归求满足条件的组合,每次取组合的下一个元素中最大的。感觉时间复杂度不是特别高,但是还是显示只有80%的用例通过,剩下的超时了。

n=int(raw_input());
all=map(int,raw_input().split());
m,d=map(int,raw_input().split());

def wangyi_sub(all,start,m,pre,d):#pre=0表示当前是第一个头,=1表示不是第一个头
    maxResult=-99999999
    minResult=99999999
    if m==1:
        if pre==0:
            maxResult=max(all[start:])
            minResult=min(all[start:])
        else:
            maxResult=max(all[start:start+d])
            minResult=min(all[start:start+d])
    else:
        if pre==0:
            maxLeft=len(all)-start-(m-1)
        else:
            maxLeft=d if d < len(all)-start-(m-1) else len(all)-start-(m-1)
        for i in xrange(start,start+maxLeft):
            preMax,preMin=wangyi_sub(all,i+1,m-1,1,d)
            nowA=all[i] * preMax
            nowB=all[i] * preMin
            if nowA>nowB:
                if nowA>maxResult:maxResult=nowA
                if nowB<minResult:minResult=nowB
            else:
                if nowB>maxResult:maxResult=nowB
                if nowA<minResult:minResult=nowA
    return maxResult,minResult
print max(wangyi_sub(all,0,m,0,d))
发表于 2017-03-21 14:39:15 回复(2)

问题信息

难度:
12条回答 71731浏览

热门推荐

通过挑战的用户

查看代码