poj1741,[poj3280]Cheapest Palindrome_區間dp

 2023-10-07 阅读 24 评论 0

摘要:Cheapest Palindrome poj-3280     題目大意:給出一個字符串,以及每種字符的加入代價和刪除代價,求將這個字符串通過刪減元素變成回文字符串的最小代價。 poj1741,    注釋:每種字符都是小寫英文字符,1<=代價cost<=

Cheapest Palindrome poj-3280

    題目大意:給出一個字符串,以及每種字符的加入代價和刪除代價,求將這個字符串通過刪減元素變成回文字符串的最小代價。

poj1741,    注釋:每種字符都是小寫英文字符,1<=代價cost<=1000,字符串長度<=2000.

      想法:通過之前兩道區間dp的鋪墊,對區間dp有了一個大概的了解,但是這道題無疑是一道比較特別的區間dp。

        首先,我們設dp狀態,這顯然是容易的:ans[i][j]表示將原字符串從i到j變成回文串的最小代價。

        之后,我們考慮轉移方程:對于一個字符串,我們顯然不可以想之前的dp一樣枚舉端點,一是回文串并不滿足兩個回文串捏一起還是回文串的性質;二是枚舉斷點的時間復雜度是$O(n^3)$的,我們并不能承受。考慮其他的轉移方式,通過回文串的性質,我們可以很清楚的明白——只有通過這個字符串的中間進行轉移才是可行的。我們想到:

        分兩種情況:

        1.s[i]==s[j]這時ans[i][j]=ans[i+1][j-1](此處注意,當這個字符串長度是2時,ans[i][j]=0)

        2.s[i]!=s[j],這時我們可以通過對于端點元素的增減來達到以第一種情況

          ans[i][j]=min(ans[i][j],min(ans[i][j]+min(val[s[j]-'0'],del[s[j]-'0']),ans[i+1][j]+min(val[s[i]-'0'],del[s[i]-'0'])));

      最后,附上丑陋的代碼... ...

#include <iostream>
#include <cstdio>
#include <cstring>
using namespace std;
char s[2010];
int ans[2010][2010];
int val[200];
int del[220];
char a[10];
int v,d;
int main()
{int n,m;scanf("%d%d",&n,&m);scanf("%s",s+1);for(int i=1;i<=n;i++){scanf("%s%d%d",a+1,&v,&d);int middle=a[1]-'0';val[middle]=v;del[middle]=d;}memset(ans,0x3f,sizeof(ans));for(int i=1;i<=m;i++){ans[i][i]=0;}for(int len=2;len<=m;len++){for(int i=1;i<=m;i++){if(i+len-1>m) break;if(s[i]==s[i+len-1]){if(len==2) ans[i][i+len-1]=0;ans[i][i+len-1]=min(ans[i][i+len-1],ans[i+1][i+len-2]);}ans[i][i+len-1]=min(ans[i][i+len-1],min(ans[i][i+len-2]+min(val[s[i+len-1]-'0'],del[s[i+len-1]-'0']),ans[i+1][i+len-1]+min(val[s[i]-'0'],del[s[i]-'0'])));}}printf("%d\n",ans[1][m]);return 0;
}

?    小結:這個題于端點的處理是很細膩的。

      在寫這個恐怖的轉移方程時注意換行,在逗號和分號都是可以換行的。

      len==2時需要特判qwq

轉載于:https://www.cnblogs.com/ShuraK/p/8520582.html

版权声明:本站所有资料均为网友推荐收集整理而来,仅供学习和研究交流使用。

原文链接:https://hbdhgg.com/5/125607.html

发表评论:

本站为非赢利网站,部分文章来源或改编自互联网及其他公众平台,主要目的在于分享信息,版权归原作者所有,内容仅供读者参考,如有侵权请联系我们删除!

Copyright © 2022 匯編語言學習筆記 Inc. 保留所有权利。

底部版权信息