【題解】LuoGu3694:邦邦的大合唱站隊

原題傳送門
暗示明顯,狀壓dpdp
狀態設計簡單,當前有多少樂隊已經排好隊爲1,其餘爲0,壓成二進制ii
dpidp_i表示狀態ii的答案

本來還一直在想如何來是最優策略,突然靈機一動
我這不是DPDP嘛,那我萬一既然有了最優策略,我還DD什麼呢

現在,只有最終狀態下樂隊的相對位置會影響答案大小
DPDP的時候按照枚舉樂隊順序從左到右放置樂隊

sumi,jsum_{i,j}表示1~j個人中有幾個是第i的樂隊的
dpj(1<<i)<—dpj+(RL+1)(sumi,Rsumi,L1)dp_{j|(1<<i)}\text{<---}dp_{j}+(R-L+1)-(sum_{i,R}-sum_{i,L-1})
其中
L1=i=1msumi,n((1<<i) and j != 0)L-1=\sum_{i=1}^{m}sum_{i,n}(\text{(1<<i) and j != 0})

Code:

//我也不知道我是腦抽了還是怎麼了,心血來潮寫個pascal
uses math;
var
    n, m, x, l, r, i, j : longint;
    power : array[0..25] of longint;
    sum : array[0..21, 0..2000010] of longint;
    dp : array[0..2000010] of longint;

begin
    readln(n, m);
    for i := 1 to n do
    begin
        readln(x);
        for j := 1 to m do 
            sum[j][i] := sum[j][i - 1];
        inc(sum[x][i]);
    end;
    power[0] := 1;
    for i := 1 to 20 do power[i] := power[i - 1] << 1;
    for i := 1 to power[m] - 1 do dp[i] := maxlongint div 2;
    for i := 0 to power[m] - 1 do
    begin
        l := 0;
        for j := 1 to m do
            if (i and power[j - 1] <> 0) then inc(l, sum[j][n]);
        for j := 1 to m do
            if (i and power[j - 1] = 0) then
                dp[i or power[j - 1]] := min(dp[i or power[j - 1]], dp[i] + sum[j][n] - sum[j][l + sum[j][n]] + sum[j][l]);
    end;
    writeln(dp[power[m] - 1]);
end.
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章