首先要注意合唱隊排好隊之後不一定是按\(1.2.3......m\)的順序的
\(n\)的範圍很大,但\(m\)的資料比較小,所以我們考慮裝壓dp
我們設\(f[i]\)為狀態為\(i\)的合唱隊已經安排好位置的最小花費
接下來就是狀態轉移方程的問題
for(int i=1;i
我們用乙個變數\(len\)記錄排好隊的總人數,如果當前合唱隊已經排好了隊,那麼我們把總人數加上當前合唱隊的人數
其中,編號為\(j\)的合唱隊的總人數\(num[j]\)可以預處理
為什麼這樣做呢?
因為我們無論讓偶像們怎麼出隊,他們最終的狀態是確定的,肯定是乙個合唱隊的偶像站到一起,因此我們就可以統計排好隊後當前區間的總長度
接下來就是狀態轉移
如果編號為\(j\)的合唱隊在我們決策的範圍之內,那我們就需要嘗試將編號為\(j\)的合唱隊的全體成員都放在隊伍最後
那麼此時我們就需要將編號為\(j\)的合唱隊中不在區間\([len-num[j]+1,num[j]]\)的偶像移到該區間
此時的花費為\(num[j]-sum[len][j]+sum[len-num[j]][j]\)
其中\(sum[i][j]\)表示開始時前\(i\)個位置中編號為\(j\)的合唱隊員的個數
問題就可以解決了
#includeusing namespace std;
const int maxn=22,maxm=1e5+5;
int f[1<
int num[maxn],sum[maxm][maxn];
int main()
memset(f,0x3f,sizeof(f));
f[0]=0;
for(int i=1;i
for(int j=1;j<=m;j++)
}printf("%d\n",f[(1<< m)-1]);
return 0;
}
洛谷 P3694 邦邦的大合唱站隊
題目鏈結 m 很小,考慮狀壓。狀態 s 一共有 m 位,每一位代表當前樂隊是否排好 即樂隊所有成員都站在一起 並假設所有排好的樂隊都站在前面。f s 表示狀態為 s 時最少移動的偶像數目。不管所有排好的樂隊順序如何,它們的總數是一定的。列舉 s 狀態中的每乙個 0 如果將它變成 1 並接在所有排好的...
P3694 邦邦的大合唱站隊
bang dream 裡的所有偶像樂隊要一起大合唱,不過在排隊上出了一些問題。n個偶像排成一列,他們來自m個不同的樂隊。每個團隊至少有乙個偶像。現在要求重新安排佇列,使來自同一樂隊的偶像連續的站在一起。重新安排的辦法是,讓若干偶像出列 剩下的偶像不動 然後讓出列的偶像乙個個歸隊到原來的空位,歸隊的位...
洛谷P3694 邦邦的大合唱站隊 簽到題
bang dream 裡的所有偶像樂隊要一起大合唱,不過在排隊上出了一些問題。n個偶像排成一列,他們來自m個不同的樂隊。每個團隊至少有乙個偶像。現在要求重新安排佇列,使來自同一樂隊的偶像連續的站在一起。重新安排的辦法是,讓若干偶像出列 剩下的偶像不動 然後讓出列的偶像乙個個歸隊到原來的空位,歸隊的位...