動態規劃部分題集解

2022-10-08 20:33:21 字數 4554 閱讀 7266

$x$ 星球的考古學家發現了一批古代留下來的密碼。

這些密碼是由 $a、b、c、d$ 四種植物的種子串成的序列。

仔細分析發現,這些密碼串當初應該是前後對稱的(也就是我們說的映象串)。

由於年代久遠,其中許多種子脫落了,因而可能會失去映象的特徵。

你的任務是:

給定乙個現在看到的密碼串,計算一下從當初的狀態,它要至少脫落多少個種子,才可能會變成現在的樣子。

輸入格式

共一行,包含乙個由大寫字母 $abcd$ 構成的字串,表示現在看到的密碼串。

輸出格式

輸出乙個整數,表示至少脫落了多少個種子。

資料範圍

輸入字串長度不超過 $1000$。

輸入樣例1:

abcba
輸出樣例1:

0
輸入樣例2:

abdcdcbabc
輸出樣例2:

3
題意就是問我們在給出的字串中,最少新增多少個字元,使其變成乙個回文字串。這題需要轉換一下思維,就是原來我們是需要找到沒有可以配對的字元,然後在某個對稱的位置新增乙個字元與其配對,或者說消滅了乙個單個不構成回文的字元,這樣就可以形成回文字串。因此整個問題可以等價於至少要刪除多少個字元可以變成回文串。刪除字元後,得到的結果應該是乙個回文字串,因此我們應該在給定的字串中找到最長的回文子串行(注意,不是回文字串)。最後要最少刪除的字元的數量就為字串總長度減去最長回文子串行,這個結果也就是最少新增的字元。

求某個字串的最長回文子串行可以用區間dp,求$\left[ \right]$區間內的最長的回文子串行的長度。

其中對於$str \left[ i \right]$在,$str \left[ j \right]$不在,以及$str \left[ i \right]$不在,$str \left[ j \right]$不在這兩種情況的集合劃分,是重複的。

比如對於$str \left[ i \right]$在,$str \left[ j \right]$不在,意味著我們要在$\left[ \right]$中找到滿足回文子串行的條件下,還應該滿足該滿足$str \left[ i \right]$是這個回文子串行的左端點。而我們的$f \left( \right)$是所有在$str \left[ \right]$中的回文子串行的集合,也就是說在這個集合中的回文子串行,$str \left[ i \right]$不一定是序列的左端點,但包含$str \left[ i \right]$為左端點的情況。因為我們還可以把$f \left( \right)$所表示的集合劃分為兩類,一類是$str \left[ i \right]$為左端點的回文子串行,另一類是$str \left[ i \right]$不為左端點的回文子串行。

因此,可以發現$f \left( \right)$是包含$str\left[ i \right]$為回文子串行左端點的這種情況,同時$f \left( \right)$所表示的集合又包含於$f \left( \right)$。雖然有重複的集合元素,但由於是求集合元素的最大值,因此即使重複也不會影響最大值。

因此這種集合劃分是保證不漏,但會有重複。我們的劃分方式是不重不漏的,但我們在計算某乙個集合的時候會計算重複的。這種劃分方式還是比較特殊的,就是如果我們發現某一種集合不好表示出來,我們可以用包含重複元素的集合來表示。求最大最小值可以這麼劃分,集合的劃分一定要保證不漏,但可以有重複。但求數量就不可以,一定要保證不重不漏。

$str \left[ i \right]$不在,$str \left[ j \right]$在也是同理。最後我們發現對於情況$str \left[ i \right]$和$str \left[ j \right]$都不在,是包含於$f \left( \right)$所表示的集合,以及$f \left( \right)$所表示的集合,因此對於這種情況我們可以不用計算,因為在算$f \left( \right)$或$f \left( \right)$的時候,已經算過$f \left( \right)$了。

ac**如下:

1 #include 2 #include 3 #include 4

using

namespace

std;56

const

int n = 1010;7

8char

str[n];

9int

f[n][n];

1011

intmain()

21else26}

27}28 printf("

%d", n - f[0][n - 1

]);29

30return0;

31 }

下面給出和這種劃分方式很像的題。

給定兩個長度分別為 $n$ 和 $m$ 的字串 $a$ 和 $b$,求既是 $a$ 的子串行又是 $b$ 的子串行的字串長度最長是多少。

輸入格式

第一行包含兩個整數 $n$ 和 $m$。

第二行包含乙個長度為 $n$ 的字串,表示字串 $a$。

第三行包含乙個長度為 $m$ 的字串,表示字串 $b$。

字串均由小寫字母構成。

輸出格式

輸出乙個整數,表示最大長度。

資料範圍

$1 \leq \leq 1000$

輸入樣例:

4

5acbd

abedc

輸出樣例:

3
這題集合的劃分和上面的那題一樣,由於是求最大值,因此集合可以有重複。

$f \left( \right)$和$f \left( \right)$是包含重複元素的,這兩個集合又包含於$f \left( \right)$所表示的集合。

ac**如下:

1 #include 2 #include 3

using

namespace

std;45

const

int n = 1010;6

7char

str1[n], str2[n];

8int

f[n][n];910

intmain() 19}

20 printf("%d"

, f[n][m]);

2122

return0;

23 }

hecy 又接了個新任務:be 處理。

be 中有一類被稱為 gbe。

以下是 gbe 的定義:

下面給出乙個 be,求至少新增多少字元能使這個 be 成為 gbe。

注意:be 是乙個僅由 ( 、) 、[ 、] 四種字元中的若干種構成的字串。

輸入格式

輸入僅一行,為字串 be。

輸出格式

輸出僅乙個整數,表示增加的最少字元數。

資料範圍

對於所有輸入字串,其長度小於 $100$。

輸入樣例:

)
輸出樣例:

1
這題也是集合的重複劃分。思路與密碼脫落一樣,需要轉換成求某段區間的子串行,子串行要滿足括號的匹配,且是最長的子串行。最後要新增的括號數量就是字串總長度減去最長的括號匹配的子串行。

情況$\left( a \right) / \left[ a \right]$的集合的劃分和上面兩題差不多一樣。而對於$ab$情況的劃分,我們把這種型別看成這種形式$()()()()...$,我們把最左邊那個匹配的括號看成乙個整體,剩下的看成另外乙個整體,即左邊是乙個$a$,右邊是若干個$a$的拼接。對於右邊可以用$f \left( \right)$來表示,左邊的話,由於沒有用於表示單獨乙個$a$這樣的集合,因此可以用$f \left( \right)$來表示,$a$這種情況的集合包含於$f \left( \right)$所表示的集合。會有重複,但不影響結果。而$a$可能包含在從$i$開始的不同長度的區間中,因此要列舉不同的區間長度。這種劃分方式有點像石子合併這題。

ac**如下:

1 #include 2 #include 3 #include 4

using

namespace

std;56

const

int n = 110;7

8char

str[n];

9int

f[n][n];

1011

intmain() 24}

25}2627 printf("

%d", n - f[1

][n]);

2829

return0;

30 }

acwing 1222. 密碼脫落(藍橋杯c++ ab組輔導課):

acwing 897. 最長公共子串行(閆氏dp分析法):

acwing 1070. 括號配對(藍橋杯c++ ab組輔導課):

動態規劃 03題

總時間限制 1000ms 記憶體限制 65536kb 描述 辰辰是個很有潛能 天資聰穎的孩子,他的夢想是稱為世界上最偉大的醫師。為此,他想拜附近最有威望的醫師為師。醫師為了判斷他的資質,給他出了乙個難題。醫師把他帶到個到處都是草藥的山洞裡對他說 孩子,這個山洞裡有一些不同的草藥,採每一株都需要一些時...

動態規劃 09題

總時間限制 1000ms 記憶體限制 65536kb 描述 桌子上有乙個m行n列的方格矩陣,將每個方格用座標表示,行座標從下到上依次遞增,列座標從左至右依次遞增,左下角方格的座標為 1,1 則右上角方格的座標為 m,n 小明是個調皮的孩子,一天他捉來乙隻螞蟻,不小心把螞蟻的右腳弄傷了,於是螞蟻只能向...

動態規劃 26 30題

總時間限制 1000ms 記憶體限制 65536kb 描述 michael喜歡滑雪百這並不奇怪,因為滑雪的確很刺激。可是為了獲得速度,滑的區域必須向下傾斜,而且當你滑到坡底,你不得不再次走上坡或者等待公升降機來載你。michael想知道載乙個區域中最長的滑坡。區域由乙個二維陣列給出。陣列的每個數字代...