网易--合唱团
網(wǎng)易–合唱團(tuán)
文章目錄
- 網(wǎng)易--合唱團(tuán)
- 一、題目描述
- 二、分析
- 三、代碼
一、題目描述
二、分析
- 這個(gè)是算法里面一直比較難的,當(dāng)我拿到這個(gè)題的時(shí)候,有點(diǎn)難以下手,雖然知道要用動(dòng)態(tài)規(guī)劃但是如何用,自己完全不知道,首先想到找出這個(gè)n個(gè)數(shù)中k個(gè)最大的相乘,但是很遺憾不對(duì),
- 題目的細(xì)節(jié)①要求相鄰兩個(gè)學(xué)生之間的編號(hào)差不能超過(guò)d,②能力值存在負(fù)數(shù)(吐槽一下,這個(gè)能力值為負(fù)數(shù)就有點(diǎn)恐怖了)。
- 接動(dòng)態(tài)規(guī)劃的套路
- (1)明確狀態(tài)與選擇:狀態(tài)就是當(dāng)前已經(jīng)選中的人數(shù)和以誰(shuí)結(jié)尾,選擇就是每個(gè)man;那么我們需要維護(hù)兩個(gè)數(shù)組,因?yàn)槟芰χ涤胸?fù)數(shù),負(fù)負(fù)會(huì)得正。
- (2)狀態(tài)轉(zhuǎn)移方程:
- 當(dāng)選中了i-1個(gè)人,以j-1結(jié)尾,再選中第j個(gè)人時(shí):
- 但由于前i-1個(gè)人的最大乘積和最小乘積不一定以第j-1個(gè)人結(jié)尾,所以我們從允許與j相隔最遠(yuǎn)的人max(1,j-D)開(kāi)始遍歷直到j(luò)-1,不斷更新dpm[i][j],dpn[i][j],最后得出的dpm[i][j],dpn[i][j]便是選中i個(gè)人,以j結(jié)尾的最大、最小乘積。
- (3)base case:
- (4)返回值:
三、代碼
#include <bits/stdc++.h> using namespace std; int main() { int n; cin>>n;//能力數(shù)組vector<int> num(n + 1); for(int i = 1; i <= n; i++) { cin>>num[i]; } //代表選擇的人數(shù)k和最大間距Dint K; int D; cin>>K>>D; //最大乘積數(shù)組//dpm[i][j]表示選中了i個(gè)人,以第j個(gè)人結(jié)尾的能力最大乘積 vector<vector<long>> dpm(K + 1,vector<long>(n + 1));//最小乘積數(shù)組//dpn[i][j]表示選中了i個(gè)人,以第j個(gè)人結(jié)尾的能力最小乘積 vector<vector<long>> dpn(K + 1,vector<long>(n + 1));;//初始化:base casefor(int j = 1; j < n + 1; j++) { dpm[1][j] = num[j]; dpn[1][j] = num[j]; } for(int i = 1; i < K + 1; i++){dpm[i][1] = num[1];dpn[i][1] = num[1];}//第一層循環(huán)代表已經(jīng)選擇的人數(shù)for(int i = 2;i < K + 1;i++){//第二層循環(huán)代表以誰(shuí)結(jié)尾for(int j = 2;j < n + 1;j++){//第三層循環(huán)代表枚舉j - D到j(luò) - 1中最大的dpm或者最小的dpn//因?yàn)閐pm[j - 1]/dpn[j - 1]并不一定是最大的for(int k = max(1,j - D);k < j;k++){dpm[i][j] = max(dpm[i][j],max(dpm[i - 1][k] * num[j],dpn[i - 1][k] * num[j]));dpn[i][j] = min(dpn[i][j],min(dpm[i - 1][k] * num[j],dpn[i - 1][k] * num[j]));}}}//循環(huán)求結(jié)果long ret = max(dpm[K][1],dpn[K][1]);for(int j = 2;j < n + 1;j++){ret = max(max(dpm[K][j],dpn[K][j]),ret);}cout<<ret<<endl;return 0;}總結(jié)
- 上一篇: 力扣--统计全1子矩阵
- 下一篇: 数据结构--图(Graph)详解(一)