1. 程式人生 > >UVa Live 4394 String painter

UVa Live 4394 String painter

題目傳送門

  傳送門

題目大意

  給定兩個字串$s$,$t$,每次可以選擇一個$s$的一個區間將它變成一個字元,問最後將$s$變成$t$的最少運算元。

  當$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\n", f[n]); 65 } 66 67 int main() { 68 while (init()) 69 solve(); 70 return 0; 71 }

相關推薦

uva live 4394 String painter 區間dp

然而 ceil 表示 cout cstring als class 求解 post // uva live 4394 String painter // // 這一題是訓練指南上dp專題的習題,初看之下認為僅僅是稍微復雜了一點 // 就敲阿敲阿敲,兩個半小時後,發現例子

UVa Live 4394 String painter - 動態規劃

題目傳送門   傳送門 題目大意   給定兩個字串$s$,$t$,每次可以選擇一個$s$的一個區間將它變成一個字元,問最後將$s$變成$t$的最少運算元。   當$s$某一段中每個字元都不同的時候,等價於對一個空串操作變成$t$的這一段。   考慮用$g_{l, r}$表示將空串

UVa Live 4394 String painter

題目傳送門   傳送門 題目大意   給定兩個字串$s$,$t$,每次可以選擇一個$s$的一個區間將它變成一個字元,問最後將$s$變成$t$的最少運算元。   當$s$某一段中每個字元都不同的時候,等價於對一個空串操作變成$t$的這一段。   考慮用$g_{l, r}$表示將空串,變成$

UVa1437 String painter

-s std 相同 cst ++ tails href 這位 targe emmm...好難的一道dp 其實本質是兩次dp.第一次求出都不相等時候的最優解, 第二次在求出兩串有相同時的更優的解. https://blog.csdn.net/hndu__lz/article/

HDU - 2476 , H - String painter [ 區間dp ]

Problem Describe There are two strings A and B with equal length. Both strings are made up of lower case letters. Now you have a powerful stri

[hdu2476]String painter(區間dp)

感覺自己發兩篇一樣的題解不太好  CQOI2007 塗色 paint (區間dp) 沒錯就是前兩天我閒得無聊發的這道題 只不過初始條件變了... 這道題初始木棍已經是塗過色的了... 然後我就又不會了 (那你為啥還在這兒發題解) 既然已經有初始顏色了,那麼就說明有的地方會是不需要塗的(

hdu 2476 String painter 動態規劃

題意:給定兩個字串a和b,求最少需要對a進行多少次操作,才能將a變成b。每次操作時將a中任意一段變成任意一個字母所組成的段。 題解:動態規劃題。dp[i][j]表示a中i到j段變成b需要的最少次數。遞推公式:dp[i][j]=min(dp[i][k]+dp[k+1][j])

UVa 1596 Bug Hunt (string::find && map && 模擬)

mic 而後 賦值 技術分享 endif 所有 模塊 發現 left 題意:給出幾組由數組定義與賦值構成的編程語句, 有可能有兩種BUG, 第一種為數組下標越界, 第二種為使用尚未定義的數組元素, 叫你找出最早出現BUG的一行並輸出, 每組以‘ . ‘號分隔, 當有兩組輸入

uva live 7637 Balanced String (貪心)

std sta print names case push live gif map 題目鏈接:https://icpcarchive.ecs.baylor.edu/index.php?option=com_onlinejudge&Itemid=8&page

DNA Consensus String,( UVa, 1368 )

log ble eof 出現 () == tps clas .net 題目鏈接 :https://vjudge.net/problem/UVA-1368 題目首先得知道什麽是Hamming距離(自行查找),然後註意出現多個解是選擇字典序小者(直接將字典序排號比較),**註意

UVA-455 利用c++ string快速解題

main uva break 循環 return sin names index == int compare( size_type index, size_type length, const basic_string &str, size_type index2

DNA Consensus String UVA - 1368

#include <iostream> #include <string> using namespace std; int m, n; // 行數,列數 string strs[50]; // 儲存每一行 int num = 0; string result; /

UVA-1368 DNA Consensus String

DNA (Deoxyribonucleic Acid) is the molecule which contains the genetic instructions. It consists of four different nucleotides, name

UVA-1368-DNA Consensus String 基礎題 貪心 模擬 詳細註釋

題意: 1. 給你一堆同長度的DNA鏈,要你計算他們共識錯誤(題目裡說的什麼漢明距離)最少的並且字典序最小的DNA鏈 2. 沒有要求多組資料輸入 思路: 1. 首先是對起到桶排序作用的陣列a進行清零操

UVa 11149 矩陣的冪(矩陣倍增法模板題)

ble 化簡 .cn target ans txt put std net https://vjudge.net/problem/UVA-11149 題意: 輸入一個n×n矩陣A,計算A+A^2+A^3+...A^k的值。 思路: 矩陣倍增法。

UVA - 434 Matty&#39;s Blocks

mes [0 () block += tty scan 一個 ems 題意:給你正視和側視圖,求最多多少個,最少多少個 思路:貪心的思想。求最少的時候:由於能夠想象著移動,盡量讓兩個視圖的重疊。所以我們統計每一個視圖不同高度的個數。然後計算。至於的話。就是每次拿正視圖的

ZOJ - 3228 Searching the String (AC自己主動機)

won key wid roc lap processor som multiple pla Description Little jay really hates to deal with string. But moondy likes it very mu

java學習筆記——String

通過 ray [] 原理 log spl 2.3 -s 長度 一、概述 ·字符串是一個特殊的對象 ·字符串一旦初始化就不可以被改變 ·String str = "abc"; ·String str1 = new String("abc"); 有什麽區別? package

java中String類型轉換為yyyy-MM-dd的Date類型

col code edate birt mat led div get sys String birthday ="2017-02-22"; SimpleDateFormat sdf = new SimpleDateFormat(("yyyy-MM-dd")); jav

利用C++ string實現任意長度小數、整數之間的加法

code include spa ctype empty esp pac space temp 1 /* 2 大數的運算1--加法: 3 利用C++ string實現任意長度小數、整數之間的加法 4 作者:大大維 5 2017/5/5