UVa Live 4394 String painter - 动态规划
Posted yyf0309
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了UVa Live 4394 String painter - 动态规划相关的知识,希望对你有一定的参考价值。
当$s$某一段中每个字符都不同的时候,等价于对一个空串操作变成$t$的这一段。
考虑用$g_{l, r}$表示将空串,变成$t_{l}t_{l + 1}cdots t_{r}$的最少操作数。
不难发现,如果我对一个区间$[l, r]$进行操作,满足下面两个条件不会更劣:
- $t_{l} = t_{r}$
- 在这之后的操作要么被$[l + 1, r - 1]$包含,要么与$[l, r]$无交。
第一点比较显然,第二点是因为如果之后的操作覆盖了$r$或者覆盖了$l$,那么这一次操作对$r$或者$l$的修改是无效的,我可以把它替换成更小的区间。
每次考虑对当前区间的第一次操作,转移可以分为下面几个:
- 如果是对整个区间进行操作,那么它必然满足$t_{l} = t_{r}$,它的操作次数等于$g_{l + 1, r}$。
- 如果没有对整个区间进行操作,那么考虑对包含左端点或者右端点的一个操作。
等价于在中间枚举一个中间点$i$,使得$t_{i} = t_{r}$或者$t_{i} = t_{s}$用$g_{l, i - 1} + g_{i, r}$或者$g_{l, i} + g_{i + 1, r}$。
考虑上原来的串$s$与空串有什么不同,如果一个位置上$s_{i} = t_{i}$,那么这个位置可以不用操作。如果我硬点它不操作,那么所有操作区间都不能跨过它。(即使操作的字符和它相等,但那样和它被看成空没有什么不同)。
所以再设$f_{i}$表示使$s$的前$i$个字符与$t$相同的最小代价。这个转移比较显然。
- 如果$s_{i} = t_{i}$,那么用$f_{i - 1}$更新$f_{i}$
- 否则枚举最后一个被当成空串的区间。
时间复杂度$O(n^{3})$
Code
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 ", f[n]); 65 } 66 67 int main() { 68 while (init()) 69 solve(); 70 return 0; 71 }
以上是关于UVa Live 4394 String painter - 动态规划的主要内容,如果未能解决你的问题,请参考以下文章
uva live 7637 Balanced String (贪心)
uva live 12846 A Daisy Puzzle Game