bang dream!裡的所有偶像樂隊要一起大合唱,不過在排隊上出了一些問題。
n個偶像排成一列,他們來自m個不同的樂隊。每個團隊至少有乙個偶像。
現在要求重新安排佇列,使來自同一樂隊的偶像連續的站在一起。重新安排的辦法是,讓若干偶像出列(剩下的偶像不動),然後讓出列的偶像乙個個歸隊到原來的空位,歸隊的位置任意。
請問最少讓多少偶像出列?
輸入格式:
第一行2個整數n,m。
接下來n個行,每行乙個整數 a_i(1\le a_i \le m)ai(1≤ai≤m) ,表示佇列中第i個偶像的團隊編號。
輸出格式:
乙個整數,表示答案
輸入樣例#1:
12 4132421
2311
34
輸出樣例#1:
7
【樣例解釋】
1 3 √
3 3
2 3 √
4 4
2 4 √
1 2 √
2 2
3 2 √
1 1
1 1
3 1 √
4 1 √
【資料規模】
對於20%的資料, n\le 20, m=2n≤20,m=2
對於40%的資料, n\le 100, m\le 4n≤100,m≤4
對於70%的資料, n\le 2000, m\le 10n≤2000,m≤10
對於全部資料, 1\le n\le 10^5, m\le 201≤n≤105,m≤20
本蒟蒻做的第一道狀壓dp. 發現根本不會怎麼搞...結果竟然不僅看了題解定義的狀態,居然還看了轉移方程(我也是水到了一定境界).
看來 dp 還是不夠啊 ! !
進入正題:
首先關於題意,有幾點需要注意:
1.每個人離開之後,會有乙個空位,而且肯定會有另外乙個人補上來.
2.最終狀態不一定要求團隊按正序排列.
狀態定義:
f [ i ] 表示當前達到這種狀態所需要請出去的最少的人.
然後關於 i 轉為 二進位制後上的每一位,都表示當前這個團隊已經站在了一起.
然後轉移方程:
j表示團隊編號,sum表示某種團隊的字首和.length表示到此已經排到的長度.
然後**裡面有解釋.
#includeusingnamespace
std;
intn,m;
int c[100008],f[1200000
];int sum[100008][25
];int
main()
}for(int i=0;i<(1
<)
f[i]=1341646
;
//賦值為極大值
f[0]=0
;
for(int i=0;i<(1
<)
}printf(
"%d\n
",f[(1
<1
]);
return0;
}
P3694 邦邦的大合唱站隊 狀壓dp
n nn個人,有m mm個隊伍,每個人都屬於乙個隊伍。要求叫出一些人來,然後任意插入出來的空隙中使得同一隊的人在一起。求最少出列人數。如果知道最終的佇列就可以十分容易的計算答案了。考慮乙個乙個隊伍的放入最終序列中,因為m mm十分的小,所以我們可以狀壓表示排好了的隊伍集合,然後用乙個字首和統計在乙個...
P3694 邦邦的大合唱站隊
bang dream 裡的所有偶像樂隊要一起大合唱,不過在排隊上出了一些問題。n個偶像排成一列,他們來自m個不同的樂隊。每個團隊至少有乙個偶像。現在要求重新安排佇列,使來自同一樂隊的偶像連續的站在一起。重新安排的辦法是,讓若干偶像出列 剩下的偶像不動 然後讓出列的偶像乙個個歸隊到原來的空位,歸隊的位...
P3694 邦邦的大合唱站隊 狀壓dp好題!!
題目 其實看這道題實際上就是列舉m個樂隊的排列,然後對應的站在該樂隊多佔的位置,卻不是該樂隊的人需要出隊。然後最後一定可站成同一團隊連續的排列。那麼下面的dp方程就很好理解啦。注意 從狀態s 在s後面放乙個樂隊j 一定需要增加的出隊的人數為 樂隊j所佔的容量num j 處不是樂隊j的人的個數。dp ...