Cheapest Palindrome(区间dp——最小花费回文串)

Cheapest Palindrome

题目

可以进行加入一个字符或删除一个字符的操作,它们都有对应代价,求这个最小代价

思路

  • 明确对任意字符的插入或删除是等价的(在该位置删除 <==> 在对称位置加入)因此每个字符的花费就是取两操作花费的min。
  • 定义dp[i][j],表示[ i , j ] 上的子串是回文的可能集合,记录它的花费W
  • 寻找状态转移,可分两类
    1. 两端点字符相同,显然从 dp[i+1][j-1] 继承过来就行 , 增加花费为0。
    2. 两端点字符不同,则可以操作左右任意一边,选择代价最小的操作

AC代码

#include<iostream>
#include<cstdio>
#include<algorithm>
#include<string>
#include<cstring>
#include<vector>
#include<queue>
#include<set>
#include<map>
#include<fstream>
#define inf 0x3f3f3f3f
#define ll long long
#define ull unsigned long long
#define endl '\n'
//#define int long long
using namespace std;
typedef pair<int,int> PII;
const int N =10 + 2e3, mod = 1e9 + 7;
int n,m;
string s;
int v[30];
ll dp[N][N];
void solve()
{    
    cin>>n>>m>>s;
    for(int i=0;i<n;i++)
    {
        int a,b;
        char c;
        cin>>c>>a>>b;
        v[c-'a'] = min(a,b);
    }
    for(int j=1;j<m;j++)// 枚举右端点向右扩散
        for(int i=j-1;i>=0;i--) // 枚举左端点向左扩散
            if(s[i] == s[j]) dp[i][j] = dp[i+1][j-1];
            else dp[i][j] = min(dp[i+1][j] + v[s[i]-'a'],dp[i][j-1] + v[s[j]-'a']);
    cout << dp[0][m-1] << endl;
}
signed main()
{
    ios::sync_with_stdio();cin.tie();cout.tie();

    solve();

    return 0;
}

枚举区间更新状态转移的顺序和平常有一些不同,原因如下

对于正常的枚举:

for(int i=0;i<n-1;i++)
		for(int j=i+1;j<n;j++)
			printf("[%d,%d], ",i,j);

区间枚举顺序如下(取n = 10)

[0,1], [0,2], [0,3], [0,4], [0,5], [0,6], [0,7], [0,8], [0,9],
[1,2], [1,3], [1,4], [1,5], [1,6], [1,7], [1,8], [1,9],
[2,3], [2,4], [2,5], [2,6], [2,7], [2,8], [2,9],
[3,4], [3,5], [3,6], [3,7], [3,8], [3,9],
[4,5], [4,6], [4,7], [4,8], [4,9],
[5,6], [5,7], [5,8], [5,9],
[6,7], [6,8], [6,9],
[7,8], [7,9],
[8,9],

根据状态转移方程, 以区间[0,8]为例

它可能从 [1,7],[1,8],[0,7] 中转移过来 ,显然此时 [1,8] 还未更新 。

因此采用AC代码中的循环顺序。

区间枚举顺序如下(n=10)

[0,1],
[1,2], [0,2],
[2,3], [1,3], [0,3],
[3,4], [2,4], [1,4], [0,4],
[4,5], [3,5], [2,5], [1,5], [0,5],
[5,6], [4,6], [3,6], [2,6], [1,6], [0,6],
[6,7], [5,7], [4,7], [3,7], [2,7], [1,7], [0,7],
[7,8], [6,8], [5,8], [4,8], [3,8], [2,8], [1,8], [0,8],
[8,9], [7,9], [6,9], [5,9], [4,9], [3,9], [2,9], [1,9], [0,9],

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值