NYOJ1023 還是回文 區間DP,詳細

2021-08-04 09:43:07 字數 2871 閱讀 8462

題目:

還是回文

時間限制:2000 ms | 記憶體限制:65535 kb

難度:3

描述 判斷回文串很簡單,把字串變成回文串也不難。現在我們增加點難度,給出一串字元(全部是小寫字母),新增或刪除乙個字元,都會產生一定的花費。那麼,將字串變成回文串的最小花費是多少呢?

輸入 多組資料

第乙個有兩個數n,m,分別表示字元的種數和字串的長度

第二行給出一串字元,接下來n行,每行有乙個字元(a~z)和兩個整數,分別表示新增和刪除這個字元的花費

所有數都不超過2000

輸出 最小花費

樣例輸入

3 4

abcb

a 1000 1100

b 350 700

c 200 800

樣例輸出

900首先我們定義

dp[i][j]代表從第i個字母到第j個字母使它成為回文串所要新增字母的個數

我們應該能想到,當只需要新增乙個字元時這個串成為回文串時,把這個字元刪去,它也可以成為乙個回文串,所以我們就可以去增加或刪除最小的數字作為花費,儲存在cost陣列裡面

那麼存在:

如果存在s[i]==s[j]的情況,我們還要處理:

為了方便理解,我詳細的解釋一下樣例:

首先我們知道了

cost[a]=1000

cost[b]=350

cost[c]=200

我們很容易知道,dp[i][i]=0

我們的陣列是:字元a

bcb編號

0123

由小區間遞推出大區間,那麼:

dp[0][1]=min(dp[1][1]+1000,dp[0][0]+350)=350

dp[1][2]=min(dp[2][2]+350,dp[1][1]+200)=200

dp[2][3]=min(dp[3][3]+200,dp[2][2]+350)=200

dp[0][2]=min(dp[1][2]+1000,dp[0][1]+200)=550

dp[1][3]=min(dp[2][3]+350,dp[1][2]+350)=550

注意,當前的s[i]與s[j]都是字元b,所以我們要比較:

dp[1][3]=min(dp[1][3],dp[2][2])=0(dp[1][3]的值為0)

dp[0][3]=min(dp[1][3]+1000,dp[0][2]+350)=900

到了這裡,上面的遞推式就很好理解了。

#include 

#include

#include

#include

#include

#include

#include

#include

#include

#include

#include

#define mem(a,b) memset(a,b,sizeof(a))

#define inf 0x3f3f3f3f

#define mod 1000007

#define n 1000

#define m 100000+50

#define ll long long

using

namespace

std;

char s[2020];

int dp[2020][2020];

char c[5];

int cost[30];//增刪字母所需要的花費

int main()

for(int k=1; kfor(int i=0; i+kint j=i+k;

dp[i][j]=min(dp[i+1][j]+cost[s[i]-'a'],dp[i][j-1]+cost[s[j]-'a']);

if(s[i]==s[j])

dp[i][j]=min(dp[i][j],dp[i+1][j-1]);

}printf("%d\n",dp[0][m-1]);

}return

0;}

#include 

#include

#include

#include

#include

#include

#include

#include

#include

#include

#include

#define mem(a,b) memset(a,b,sizeof(a))

#define inf 0x3f3f3f3f

#define mod 1000007

#define n 1000

#define m 100000+50

#define ll long long

using

namespace

std;

char s[2020];

int dp[2020][2020];

char c[5];

int cost[30];//增刪字母所需要的花費

int main()

for(int k=1; kfor(int i=0; i+kint j=i+k;

if(s[i]==s[j])

dp[i][j]=dp[i+1][j-1];

else

dp[i][j]=min(dp[i+1][j]+cost[s[i]-'a'],dp[i][j-1]+cost[s[j]-'a']);

}printf("%d\n",dp[0][m-1]);

}return

0;}

NYOJ1023 還是回文(區間dp)

分析 這道題是乙個簡單區間的dp,狀態定義為dp i j i 到 j 這個區間形成回文的最小花費,分兩種情況討論 s i s j dp i j dp i 1 j 1 s i s j dp i j min dp i j 1 cost s j a dp i 1 j cost s i a cost tt ...

NYOJ 1023 還是回文 區間dp

時間限制 2000 ms 記憶體限制 65535 kb 難度 3描述 判斷回文串很簡單,把字串變成回文串也不難。現在我們增加點難度,給出一串字元 全部是小寫字母 新增或刪除乙個字元,都會產生一定的花費。那麼,將字串變成回文串的最小花費是多少呢?輸入多組資料 第乙個有兩個數n,m,分別表示字元的種數和...

NYOJ 1023 還是回文

時間限制 2000 ms 記憶體限制 65535 kb 難度 3 描述判斷回文串很簡單,把字串變成回文串也不難。現在我們增加點難度,給出一串字元 全部是小寫字母 新增或刪除乙個字元,都會產生一定的花費。那麼,將字串變成回文串的最小花費是多少呢?輸入多組資料 第乙個有兩個數n,m,分別表示字元的種數和...