题目:题目链接
题意:输入两个长度分别为n和m的颜色序列,要求按顺序合并成同一个序列,即每次可以把一个序列开头的颜色放到新序列的尾部。对于每个颜色c来说,其跨度L(c)等于最大位置和最小位置之差,输出各颜色跨度之和。
思路:设d(i, j)表示两个序列分别移走了i和j个元素,还需要多少费用。每移一次,我们需要对已经出现但没有结束的颜色跨度加一,用数组c表示已经开始但没有结束的颜色数量,我们得到状态转移方程:dp(i,j)=min(dp(i-1,j)+c[i-1][j],dp(i,j-1)+c[i][j-1])。
AC代码:
1 #include <iostream> 2 #include <cstdio> 3 #include <cstdlib> 4 #include <cstring> 5 #include <cmath> 6 #include <algorithm> 7 #include <vector> 8 #include <string> 9 #include <map> 10 #include <set> 11 #include <unordered_map> 12 #include <unordered_set> 13 #include <queue> 14 #include <stack> 15 #include <list> 16 17 #define FRER() freopen("in.txt", "r", stdin) 18 #define FREW() freopen("out.txt", "w", stdout) 19 20 #define INF 0x3f3f3f3f 21 22 using namespace std; 23 24 const int maxn = 5000 + 5; 25 26 char str[maxn], ptr[maxn]; 27 28 int ss[26], sp[26], es[26], ep[26]; 29 30 int d[maxn][maxn], c[maxn][maxn]; 31 32 int main() 33 { 34 ios::sync_with_stdio(0); 35 cin.tie(0); 36 int T; 37 cin >> T; 38 while(T--) { 39 cin >> (str + 1) >> (ptr + 1); 40 41 int n = strlen(str + 1), m = strlen(ptr + 1); 42 43 memset(ss, INF, sizeof(ss)); 44 memset(sp, INF, sizeof(sp)); 45 memset(es, 0, sizeof(es)); 46 memset(ep, 0, sizeof(ep)); 47 48 for(int i = 1; i <= n; ++i) { 49 ss[str[i] - 'A'] = min(ss[str[i] - 'A'], i); 50 es[str[i] - 'A'] = i; 51 } 52 for(int i = 1; i <= m; ++i) { 53 sp[ptr[i] - 'A'] = min(sp[ptr[i] - 'A'], i); 54 ep[ptr[i] - 'A'] = i; 55 } 56 57 for(int i = 0; i <= n; ++i) { 58 for(int j = 0; j <= m; ++j) { 59 if(!i && !j) continue; 60 int v1 = INF, v2 = INF; 61 if(i) v1 = d[i - 1][j] + c[i - 1][j]; 62 if(j) v2 = d[i][j - 1] + c[i][j - 1]; 63 d[i][j] = min(v1, v2); 64 65 if(i) { 66 c[i][j] = c[i - 1][j]; 67 if(ss[str[i] - 'A'] == i && sp[str[i] - 'A'] > j) c[i][j]++; 68 if(es[str[i] - 'A'] == i && ep[str[i] - 'A'] <= j) c[i][j]--; 69 } 70 71 else if(j) { 72 c[i][j] = c[i][j - 1]; 73 if(sp[ptr[j] - 'A'] == j && ss[ptr[j] - 'A'] > i) c[i][j]++; 74 if(ep[ptr[j] - 'A'] == j && es[ptr[j] - 'A'] <= i) c[i][j]--; 75 } 76 } 77 } 78 79 cout << d[n][m] << endl; 80 } 81 return 0; 82 }