标签:更新 没有 uvalive line 不同 fill otto std ios
当$s$某一段中每个字符都不同的时候,等价于对一个空串操作变成$t$的这一段。
考虑用$g_{l, r}$表示将空串,变成$t_{l}t_{l + 1}\cdots t_{r}$的最少操作数。
不难发现,如果我对一个区间$[l, r]$进行操作,满足下面两个条件不会更劣:
第一点比较显然,第二点是因为如果之后的操作覆盖了$r$或者覆盖了$l$,那么这一次操作对$r$或者$l$的修改是无效的,我可以把它替换成更小的区间。
每次考虑对当前区间的第一次操作,转移可以分为下面几个:
考虑上原来的串$s$与空串有什么不同,如果一个位置上$s_{i} = t_{i}$,那么这个位置可以不用操作。如果我硬点它不操作,那么所有操作区间都不能跨过它。(即使操作的字符和它相等,但那样和它被看成空没有什么不同)。
所以再设$f_{i}$表示使$s$的前$i$个字符与$t$相同的最小代价。这个转移比较显然。
时间复杂度$O(n^{3})$
1 /** 2 * UVa Live 3 * Problem#4394 4 * Accepted 5 * Time: 43ms 6 */ 7 #include <iostream> 8 #include <cstdlib> 9 #include <cstring> 10 #include <cstdio> 11 using namespace std; 12 typedef bool boolean; 13 14 template <typename T> 15 void pfill(T* pst, const T* ped, T val) { 16 for (; pst != ped; *(pst++) = val); 17 } 18 19 const int N = 105; 20 const signed inf = (signed) (~0u >> 1); 21 22 int n; 23 char A[N], B[N]; 24 int f[N], g[N][N]; 25 boolean vis[N][N]; 26 27 inline boolean init() { 28 if (scanf("%s", A + 1) == -1) 29 return false; 30 scanf("%s", B + 1); 31 n = strlen(A + 1); 32 return true; 33 } 34 35 int dp(int l, int r) { 36 if (l == r) 37 return 1; 38 if (vis[l][r]) 39 return g[l][r]; 40 int& rt = g[l][r]; 41 rt = inf, vis[l][r] = true; 42 if (B[l] == B[r]) 43 rt = min(dp(l + 1, r), dp(l, r - 1)); 44 45 for (int i = l; i < r; i++) 46 if (B[l] == B[i]) 47 rt = min(rt, dp(l, i) + dp(i + 1, r)); 48 for (int i = l + 1; i <= r; i++) 49 if (B[i] == B[r]) 50 rt = min(rt, dp(l, i - 1) + dp(i, r)); 51 return rt; 52 } 53 54 inline void solve() { 55 pfill(vis[1], vis[n + 1], false); 56 f[0] = 0; 57 for (int i = 1; i <= n; i++) { 58 f[i] = inf; 59 if (A[i] == B[i]) 60 f[i] = f[i - 1]; 61 for (int j = i; j; j--) 62 f[i] = min(f[i], f[j - 1] + dp(j, i)); 63 } 64 printf("%d\n", f[n]); 65 } 66 67 int main() { 68 while (init()) 69 solve(); 70 return 0; 71 }
UVa Live 4394 String painter - 动态规划
标签:更新 没有 uvalive line 不同 fill otto std ios
原文地址:https://www.cnblogs.com/yyf0309/p/9912275.html