習題 大理石(狀壓DP)

2021-09-27 10:34:51 字數 1380 閱讀 6447

zz是一位大理石收藏家,他在家裡收藏了n塊各種顏色的大理石,第i塊大理石的顏色為ai。但是zz覺得這些石頭在家裡隨意擺放太過凌亂,他希望把所有顏色相同的石頭放在一起。換句話說,zz需要對現有的大理石重新進行排列,在重新排列之後,對於每乙個顏色j,如果最左邊的顏色為j的大理石是第l塊大理石,最右邊的顏色為j的大理石是第r塊大理石,那麼從第l塊大理石到第r塊大理石,這些石頭的顏色都為j。

由於這些大理石都比較重,zz無法承受這些大理石的重量太久,所以他每次搬運只能交換相鄰的兩塊大理石。請問,zz最少需要進行多少次搬運?

第一行輸入乙個數字n(2≤n≤4*10^5),表示大理石的總數。

第二行輸入n個數字a1,a2…,an(1≤ai≤20)表示第i塊大理石的顏色為ai。

輸出zz最少需要搬運的次數。

n很大,但是顏色少啊,很明顯的乙個狀壓dp的題,狀態的表示0即為當前

位置的顏色沒有完成,1則表示為完成了

定義乙個陣列表示g[25

][25]

g[25][25]

g[25][

25]表示i號顏色前j號顏色一共有多少個,

d p[

i]=m

in(d

p[i]

,dp[

i−j]

+cos

t(i,

j)

)dp[i]=min(dp[i],dp[i-j]+cost(i,j))

dp[i]=

min(

dp[i

],dp

[i−j

]+co

st(i

,j))

#include #include using namespace std;

#define int long long

int n;

int a[400005];

int cost[400005][25]; // i為前顏色為j有多少個

int c[25][25]; //表示第i個顏色前有多少個j顏色

int dp[(1 << 21)];

int solve_cost(int col, int t)

return ans;

}signed main()

for (int i = 1; i <= n; i++)

for (int i = 1; i <= n; i++)

}memset(dp, 127, sizeof(dp));

dp[0] = 0;

for (int i = 1; i <= (1 << 20); i++) }}

cout << dp[(1 << 20) - 1];

return 0;

}

週末訓練 大理石

記憶體限制 256 mib 時間限制 4000 ms 標準輸入輸出 題目型別 傳統 評測方式 文字比較 林老師是一位大理石收藏家,他在家裡收藏了 n 塊各種顏色的大理石,第 i 塊大理石的顏色為 a i 但是林老師覺得這些石頭在家裡隨意擺放太過凌亂,他希望把所有顏色相同的石頭放在一起。換句話說,林老...

週末訓練 大理石

記憶體限制 256 mib 時間限制 4000 ms 標準輸入輸出 題目型別 傳統 評測方式 文字比較 林老師是一位大理石收藏家,他在家裡收藏了 n 塊各種顏色的大理石,第 i 塊大理石的顏色為 a i 但是林老師覺得這些石頭在家裡隨意擺放太過凌亂,他希望把所有顏色相同的石頭放在一起。換句話說,林老...

大理石在哪兒

現有n各大理石,每個大理石上寫著乙個非負整數。首先把各數從小到大排序,然後回答q各問題。每個問題問是否有乙個大理石寫著某個整數x,如果是,還要回答哪個大理石上寫著x。排序後的大理石從左到右編號為1 n。樣例輸入 4 11 3 5 1 55 2 1 3 3 3 1 2 3樣例輸出 case 1 5 f...