AT???? [ABC255D] String Cards 題解
阿新 • • 發佈:2021-10-31
Link.
Description.
有 \(n\) 個字串,選出 \(K\) 個按任意順序連線。
求字典序最小的方案。
\(1\le k\le n\le 50\)
Solution.
首先,當 \(K=n\) 的情況是一個經典原題。
可以直接 sort(s.begin(),s.end(),[](string a,string b){return a+b<b+a;});
就做完了。
這個滿足偏序也很好證明,可以直接算雜湊值。
這樣就有 \(a\times 26^{|B|}+b\le b\times26^{|A|}+a\),有 \(\frac{a}{26^{|A|}-1}\le \frac{b}{26^{|B|}-1}\)
同時,排完序後,選出來 \(K\) 個肯定會按原序列順序排序,證明顯然。
然後,\(K\ne n\) 的時候考慮 dp。
dp 要求的是全域性最優決策的部分肯定是區域性最優決策。
從前往右肯定有問題,因為 a
和 aa
區域性最優決策是 a
,但是後面連一個 b
就要選 aab
。
考慮從後往前,往前接一個相同的字串,後面肯定字典序越小越好。
所有從後往前 dp 就行了。
Coding.
點選檢視程式碼
//Coded by leapfrog on 2021.10.29 {{{ //是啊,你就是那隻鬼了,所以被你碰到以後,就輪到我變成鬼了 #include<bits/stdc++.h> using namespace std;typedef long long ll; template<typename T>inline void read(T &x) { x=0;char c=getchar(),f=0; for(;c<48||c>57;c=getchar()) if(!(c^45)) f=1; for(;c>=48&&c<=57;c=getchar()) x=(x<<1)+(x<<3)+(c^48); f?x=-x:x; } template<typename T,typename...L>inline void read(T &x,L&...l) {read(x),read(l...);}//}}} string s[55],dp[55][55];int n,K; int main() { read(n,K);for(int i=1;i<=n;i++) cin>>s[i]; sort(s+1,s+n+1,[](string a,string b){return a+b<b+a;}); for(int i=n;i>=1;i--) { dp[i][n-i+1]=s[i]+dp[i+1][n-i]; for(int j=1;j<=n-i;j++) dp[i][j]=min(dp[i+1][j],s[i]+dp[i+1][j-1]); }return cout<<dp[1][K]<<endl,0; }