在線判題通道:??途W(wǎng)-HJ24 合唱隊(duì)
成都創(chuàng)新互聯(lián)公司專業(yè)為企業(yè)提供香洲網(wǎng)站建設(shè)、香洲做網(wǎng)站、香洲網(wǎng)站設(shè)計(jì)、香洲網(wǎng)站制作等企業(yè)網(wǎng)站建設(shè)、網(wǎng)頁設(shè)計(jì)與制作、香洲企業(yè)網(wǎng)站模板建站服務(wù),10年香洲做網(wǎng)站經(jīng)驗(yàn),不只是建網(wǎng)站,更提供有價值的思路和整體網(wǎng)絡(luò)服務(wù)。題目描述:N 位同學(xué)站成一排,音樂老師要請最少的同學(xué)出列,使得剩下的 K 位同學(xué)排成合唱隊(duì)形。
通俗來說,能找到一個同學(xué),他的兩邊的同學(xué)身高都依次嚴(yán)格降低的隊(duì)形就是合唱隊(duì)形。
例子:
123 124 125 123 121 是一個合唱隊(duì)形
123 123 124 122不是合唱隊(duì)形,因?yàn)榍皟擅瑢W(xué)身高相等,不符合要求
123 122 121 122不是合唱隊(duì)形,因?yàn)檎也坏揭粋€同學(xué),他的兩側(cè)同學(xué)身高遞減。
你的任務(wù)是,已知所有N位同學(xué)的身高,計(jì)算最少需要幾位同學(xué)出列,可以使得剩下的同學(xué)排成合唱隊(duì)形。
注意:不允許改變隊(duì)列元素的先后順序 且 不要求最高同學(xué)左右人數(shù)必須相等
輸入描述:
用例兩行數(shù)據(jù),第一行是同學(xué)的總數(shù) N ,第二行是 N 位同學(xué)的身高,以空格隔開
輸出描述:
最少需要幾位同學(xué)出列
示例1
輸入:
8
186 186 150 200 160 130 197 200
輸出:
4
說明:
由于不允許改變隊(duì)列元素的先后順序,所以最終剩下的隊(duì)列應(yīng)該為186 200 160 130或150 200 160 130
代碼(詳細(xì)注釋代碼在下面):#includeusing namespace std;
int n,a[3001],f1[3001],f2[3001],MAX;
int main()
{
cin>>n;
for(int i=1;i<=n;i++) {
cin>>a[i];
f1[i] = 1;
for(int j=1;ji;j--)
{
if(a[j]
題解+詳細(xì)注釋版代碼合唱隊(duì)問題歸結(jié)下來是求兩個大上升子序列的長度問題,從隊(duì)列正方向得到所有的大上升子序列,再從反方向得到所有的大上升子序列(即為大下降子序列),找出兩個組合起來總長度大的情況即為最終答案,所以問題簡化為求大上升子序列的問題。
首先這個是課本上的內(nèi)容,已經(jīng)介紹的非常詳細(xì),如果看不太懂的話建議配合課本給出的例題,推算一下實(shí)際每步產(chǎn)生的隊(duì)列是哪幾個具體的同學(xué),就會非常清晰了
如何理解代碼&我遇到的問題&解決思路&代碼理解下面我就帶著大家,從我當(dāng)時理解算法&寫代碼的時候遇到問題問題出發(fā),帶大家理解一下代碼
我的在coding過程中的大問題不是對大上升子序列的理解沒到位,所以上面的介紹就簡單過,主要是下面談一下我遇到的代碼上的大的問題:
問題:在尋找大上升子序列時 書上的動歸方程給出的是
但是實(shí)際在代碼中,沒有能對一個集合內(nèi)多個元素同時求出一個大值的操作 所以需要使用一個循環(huán)來遍歷實(shí)現(xiàn),我就是在這個循環(huán)的地方卡了很久的理解:
for(int i=1;i<=n;i++) {
cin>>a[i];
f1[i] = 1;//問題①:方程中只給出了f1[1] = 1的遞歸出口
? ? ? ? //但是在代碼中是將所有的f1[i]的初始值都給成了1
for(int j=1;j
然后我想著搞不懂就自己推一遍過程
于是得到了答案:
問題①:給數(shù)組內(nèi)所有元素賦值為1是為了防止出現(xiàn)如2 5 1這樣的排列的時候到了第三個同學(xué)高度為1 則此時大上升子序列的值應(yīng)該為1,如果不整體賦初值的話,到第三個同學(xué)這里,上升序列的長度就是0了
但是這好像仍然不能解決問題②,于是我研究了下這個循環(huán)
這里使用了循環(huán)for(int j=1;j
a[3] = 5 >a[4] = 3 導(dǎo)致f[4] = 1
而使用循環(huán)會保證和前面所有的上升子串都進(jìn)行了一次比較
j=1:a[1]< a[4] = 3 -->f[4] = f1[1] + 1 = 2
表示序列f1[1] + 第4個同學(xué)可以組成新序列1 3且長度為2
j=2:a[2]< a[4] = 3 -->f[4] = f1[2] + 1 = 3
表示序列f2[1] + 第4個同學(xué)可以組成新序列1 2 3且長度為3
j=1:a[3] >a[4] = 3 -->f[4] = f1[2] = 3
5 >3 則第三個序列f[3]無法和第4個同學(xué)組成新序列 序列長度還是之前的3
得出序列f[4]大值為3
所以for(int j=1;j
f1[j]代表到第j個同學(xué)的大上升子串 則為了求集合大值 使用了一次循環(huán)遍歷
如果a[i] >a[j]說明第i個同學(xué)要比第j個同學(xué) 和第j個同學(xué)已經(jīng)建立起的上升子序列中所有同學(xué)都高,則上升子序列的大值,就可以更新為已經(jīng)建立的上升子序列f1[j]加上同學(xué)a[i] 表示為f1[j] + 1
詳細(xì)注釋版代碼#includeusing namespace std;
int n,a[3001],f1[3001],f2[3001],MAX;//f1[i]表示上升子序列的個數(shù) f2[i]表示反方向開始的上升子序列的個數(shù)
int main()
{
cin>>n;
for(int i=1;i<=n;i++)//下標(biāo)從1開始
{
cin>>a[i];
f1[i] = 1;//這里很關(guān)鍵 遞歸邊界是f[1] = 1 以及每個上升子序列的最小值為1
//但是給數(shù)組內(nèi)所有元素賦值為1是為了防止出現(xiàn)如2 5 1這樣的排列的時候
//到了第三個同學(xué)高度為1 則此時大上升子序列的值應(yīng)該為1
for(int j=1;ja[4] = 3 導(dǎo)致f[4] = 1
//而使用循環(huán)會保證和前面所有的上升子串都進(jìn)行了一次比較
//j=1:a[1]< a[4] = 3 -->f[4] = f1[1] + 1 = 2
//表示序列f1[1] + 第4個同學(xué)可以組成新序列1 3且長度為2
//j=2:a[2]< a[4] = 3 -->f[4] = f1[2] + 1 = 3
//表示序列f2[1] + 第4個同學(xué)可以組成新序列1 2 3且長度為3
//j=1:a[3] >a[4] = 3 -->f[4] = f1[2] = 3
//5 >3 則第三個序列f[3]無法和第4個同學(xué)組成新序列 序列長度還是之前的3
//得出序列f[4]大值為3
}
}
for(int i=n;i>=1;i--)
{
f2[i] = 1;
for(int j=n;j>i;j--)
{
if(a[j]
你是否還在尋找穩(wěn)定的海外服務(wù)器提供商?創(chuàng)新互聯(lián)www.cdcxhl.cn海外機(jī)房具備T級流量清洗系統(tǒng)配攻擊溯源,準(zhǔn)確流量調(diào)度確保服務(wù)器高可用性,企業(yè)級服務(wù)器適合批量采購,新人活動首月15元起,快前往官網(wǎng)查看詳情吧