[UVa-437] Color Length
計算貢獻;壓縮空間優化時間
傳送門:$>here<$
題意
給出兩個字符串$a$,$b$,將他們穿插起來(相對位置不變),要求最小化$\sum L(c)$,其中$L(c)$的定義時在穿插完的字符串中字符$c$的最大位置與最小位置的差。
數據范圍:$n \leq 5000$
Solution
問題的轉化
根據$LCS$的模型容易想到$dp_{i,j}$表示$a$的前$i$個與$b$的前$j$個穿插后的最小$L$。轉移即接$i$或接$b$.
如何轉移呢?如果要利用這樣的狀態進行轉移,肯定需要知道每種字符出現的最早位置。這樣的話狀態就變得很大了……
既然用直接的方法無法進行轉移,那么必須改變計算方法!將dp(i,j)的意義改為將a的前i個與b的前j個合并后對最終答案的最優貢獻。也就是說,不要將dp(i,j)作為子問題去考慮,而是考慮這一部分對整體的貢獻。
將題目要求的某種字符的最大位置與最小位置的差看做一條線段,這條線段從這個字符首次出現開始延伸,直到最后一個這種字符出現。那么題目要求最小化的就是26根線段的總長度。那么dp(i,j)就是表示填完a的前i個與b的前j個以后線段的最小總長。
利用DP來解決
要計算最小總長(假設現在選擇將a[i]放在最后),那么就考慮將a[i]填入后總長增加多少?很顯然,對于那些還沒有出現完的字符,它們對應的線段長度就要+1。什么意思?對于a[i]前面的每種字符,若還有可能在a[i]后方出現,那么對應的線段長度需要延伸。如果某種字符在a[i]之后再也不會出現了,那就不用延伸了。因此,填完a[i]后延伸的總長度就是還沒有出現完的字符個數。
值得注意的是,這里的dp(i,j)既然不是子問題,那是如何保證DP的性質的呢?結合深搜來理解一下,假設最終字符的最后幾位怎么填已經知道,那么前面怎么填最優?由于之前出現了哪些字符是確定的,因此最后幾位在填的時候延伸的總長度是確定的,那么也就是最小化前面的總長度,那么也就是dp(i,j)了。
透過題解看本質
問題的轉化
當發現當前問題極難轉移時,不妨換一種計算思路。既然子問題無法考慮,那就整體考慮。
形象生動
把位置之差理解為線段很直觀便于思考。避免去空想那些太抽象的東西 。
部分解并不獨立有意義
不僅僅是因為這道題部分考慮比較難所以選擇整體考慮,而是因為這道題的很多部分解對于轉移是沒有意義的。
my code
值得注意的是如果用二維DP會炸。幸好可以直接滾動數組變成1維。
還發現優化空間能夠幫助優化時間。
/*By DennyQi 2019*/ #include <cstdio> #include <queue> #include <cstring> #include <algorithm> using namespace std; typedef long long ll; const int MAXN = 10010; const int MAXM = 20010; const int INF = 0x3f3f3f3f; inline int Max(const int a, const int b){ return (a > b) ? a : b; } inline int Min(const int a, const int b){ return (a < b) ? a : b; } inline int read(){int x = 0; int w = 1; register char c = getchar();for(; c ^ '-' && (c < '0' || c > '9'); c = getchar());if(c == '-') w = -1, c = getchar();for(; c >= '0' && c <= '9'; c = getchar()) x = (x<<3) + (x<<1) + c - '0'; return x * w; } int T,dp[5010],cnt[5010],lsta[30],lstb[30],fsta[30],fstb[30],la,lb; char a[5010],b[5010]; inline void Init_cnt(){memset(lsta,0,sizeof(lsta));memset(lstb,0,sizeof(lstb));memset(fsta,0x3f,sizeof(fsta));memset(fstb,0x3f,sizeof(fstb));for(int i = 1; i <= la; ++i){lsta[a[i]-'A'] = max(lsta[a[i]-'A'],i);fsta[a[i]-'A'] = min(fsta[a[i]-'A'],i);}for(int i = 1; i <= lb; ++i){lstb[b[i]-'A'] = max(lstb[b[i]-'A'],i);fstb[b[i]-'A'] = min(fstb[b[i]-'A'],i);} } inline void DP(){memset(dp,INF,sizeof(dp));memset(cnt,0,sizeof(cnt));char cur;dp[0] = 0;for(int i = 0; i <= la; ++i){for(int j = 0; j <= lb; ++j){if(i==0 && j==0) continue;if(i == 0){ cnt[j] = cnt[j-1];cur = b[j]-'A';if(j == fstb[cur]) ++cnt[j];if(j == lstb[cur] && lsta[cur] == 0) --cnt[j];}else{cur = a[i]-'A';if(j >= lstb[cur] && i >= lsta[cur]) --cnt[j];if(j < fstb[cur] && i == fsta[cur]) ++cnt[j];}dp[j] = min((j==0)?INF:dp[j-1], (i==0)?INF:dp[j])+cnt[j];}} } int main(){scanf("%d",&T);while(T--){scanf("%s%s",a+1,b+1);la = strlen(a+1), lb = strlen(b+1);Init_cnt();DP();printf("%d\n",dp[lb]);}return 0; }轉載于:https://www.cnblogs.com/qixingzhi/p/10390174.html
總結
以上是生活随笔為你收集整理的[UVa-437] Color Length的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 第五周助教心得体会
- 下一篇: 图书管理销售系统需求分析报告,对性能的规