[USACO07OPEN]便宜的回文Cheapest Palindrome

字串S长M,由N个小写字母构成。欲通过增删字母将其变为回文串,增删特定字母花费不同,求最小花费。

       题目描述见上

     

     显然 这是一道区间DP

       从两头DP,枚举长度啥的很套路了。具体细节请参见代码qwq

  

#include<iostream> 
#include<cstdio>
#include<cstring>
#define re register int
#define maxn 2000+5
#define maxn1 3000+5
int val[maxn],dp[maxn1][maxn1],val1,val2;
char ch[maxn1],temp[3];
using namespace std;
inline int read()
{
int x=0,f=1;
char ch=getchar();
while(!isdigit(ch))
{
if(ch=='-') f=-1;
ch=getchar();
}
while(isdigit(ch))
{
x=(x<<3)+(x<<1)+ch-'0';
ch=getchar();
}
return x*f;
}
int main()
{
int n,m;
memset(dp,0x3f,sizeof(dp));//必须要初始化 
n=read();
m=read();
scanf("%s",ch+1);
for(re i=1;i<=n;i++)
{
cin>>temp[0];
val1=read();
val2=read();
val[temp[0]-'a']=min(val1,val2);
//易得从中间插入或删除是等效的 
}
for(re i=1;i<=m;i++)
{
dp[i][i]=0;
if(ch[i]==ch[i+1]) dp[i][i+1]=0;
}
for(re len=0;len<=m;len++)
//len必须从0枚举
//否则会少算情况(连样例都过不了QAQ) 
for(re i=1;i<=m;i++)
{
int j=len+i;
int x1=ch[i-1]-'a';
int x2=ch[j+1]-'a';
if(x1==x2) dp[i-1][j+1]=min(dp[i-1][j+1],dp[i][j]);
dp[i-1][j]=min(dp[i-1][j],dp[i][j]+val[x1]);
dp[i][j+1]=min(dp[i][j+1],dp[i][j]+val[x2]);
//每种状态都需要算一遍
//因为不知道会从哪个扩展 
}
cout<<dp[1][m];
return 0;

}

 
View Code

 

转载于:https://www.cnblogs.com/3200Pheathon/p/10684438.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值