日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

【CF1215E】Marbles【状压DP】

發布時間:2023/12/3 编程问答 43 豆豆
生活随笔 收集整理的這篇文章主要介紹了 【CF1215E】Marbles【状压DP】 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

傳送門

題意:給一個長為NNN的序列aaa,每次操作交換兩個相鄰位置,求最少操作次數使得所有相同的值連成一片。

N≤400000N \leq 400000N400000,ai≤20a_i \leq20ai?20

我們發現aia_iai?很小,盲猜單獨考慮

我們重新確認一個宏大的時空觀

把所有位置按值分組,然后一組一組加進去。在某一組沒有加之前,這個位置是不存在的,即1 3 2在沒有加3時,1 2是相鄰的。

cnt[i][j]cnt[i][j]cnt[i][j]表示只有iiijjj兩組數時,把所有iii移到jjj的前面的最小操作次數

這個可以暴力枚舉iiijjj,然后雙指針即可

考慮狀壓

dp[S]dp[S]dp[S]表示當前加入的數的狀態為SSS的最小操作次數 我們新加一個數時,把散裝的都移到最前面。因為cntcntcnt是單獨考慮的,所以加起來就可以了

dp[S]=min?i∈S{dp[S?{i}]+∑j∈S,i≠jcnt[i][j]}dp[S]=\min_{i \in S}\{dp[S-\{i\}]+\sum_{j\in S,i\neq j}cnt[i][j]\}dp[S]=iSmin?{dp[S?{i}]+jS,i?=j?cnt[i][j]}

最后的dp[2n?1]dp[2^n-1]dp[2n?1]即答案

復雜度O(na2+2aa2)O(na^2+2^aa^2)O(na2+2aa2)

#include <iostream> #include <cstdio> #include <cstring> #include <cctype> #include <vector> using namespace std; typedef long long ll; inline int read() {int ans=0;char c=getchar();while (!isdigit(c)) c=getchar();while (isdigit(c)) ans=(ans<<3)+(ans<<1)+(c^48),c=getchar();return ans; } vector<int> v[20]; ll cnt[20][20],dp[1<<20]; int main() {int n=read();for (int i=1;i<=n;i++) v[read()-1].push_back(i);for (int i=0;i<20;i++)for (int j=0;j<20;j++)if (i!=j){int pos=-1;for (int k=0;k<v[i].size();k++){while (pos+1<v[j].size()&&v[j][pos+1]<v[i][k]) ++pos;cnt[i][j]+=pos+1;}}dp[0]=0;for (int s=1;s<(1<<20);s++){dp[s]=1e18;for (int i=0;i<20;i++)if (s&(1<<i)){ll sum=0;for (int j=0;j<20;j++)if (s&(1<<j))sum+=cnt[i][j];dp[s]=min(dp[s],dp[s^(1<<i)]+sum); } }cout<<dp[(1<<20)-1];return 0; }

總結

以上是生活随笔為你收集整理的【CF1215E】Marbles【状压DP】的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。