poj-3280-Cheapest Palindrome

呂振麒 bio photo By 呂振麒 Comment

傳送門

Cheapest Palindrome

題意

給一字串,求轉成迴文的最小花費 (新增、刪除字元皆有花費)

思路

首先簡化一下問題:
透過觀察發現,需要新增字元時也可以選擇把該字元移除,於是稱新增或刪除一個字元為操作一個字元,所需的花費為 min(新增該字元, 刪除該字元)

令 dp[x][y] : 區間 [x, y) 轉成迴文的最小花費
初始: 所有長度1或0的區間已經是迴文,為0
接著我們思考如何透過已是迴文的部分來組出更長的迴文,或說
某區間如何透過已經做好的部分來完成
結果如下:

每個區間[x, y)我們可以選擇
操作最左(x)或最右(y-1)邊的字元來使此區間成為迴文:

  • dp[x][y] = dp[x+1][y] + cost(str[x])
  • dp[x][y] = dp[x][y-1] + cost(str[y-1])

如果該區間最左與最右邊的字元相同:

  • dp[x][y] = dp[x+1][y-1]
需依區間長度由小到大建dp表!

code

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
#include <iostream>
#include <algorithm>
using namespace std;

int T,M,N,K,I,b,c,ans,cnt;
char a;
int cost[200], dp[2002][2002];
string str;

int main(){
  ios::sync_with_stdio(false);cin.tie(0);
  cin>>N>>M>>str;
  for(int i=0;i<N;i++){
    cin>>a>>b>>c;
    cost[a] = min(b, c);
  }
  for(int i=2 ; i<=M ; i++) for(int j=0 ; j+i<=M ; j++){
    dp[j][j+i] = min(dp[j][j+i-1] + cost[str[j+i-1]], dp[j+1][j+i] + cost[str[j]]);
    if(str[j] == str[j+i-1])
      dp[j][j+i] = min(dp[j][j+i], dp[j+1][j+i-1]);
  }
  cout<<dp[0][M]<<endl;
}
comments powered by Disqus