2481: 神奇的字符串
时间限制: 3 Sec 内存限制: 256 MB
提交: 8 解决: 3
[提交][状态][讨论版]
题目描述
输入
输出
样例输入
abcb
1000 1100
350 700
200 800
2000 2000
2000 2000
2000 2000
2000 2000
2000 2000
2000 2000
2000 2000
2000 2000
2000 2000
2000 2000
2000 2000
2000 2000
2000 2000
2000 2000
2000 2000
2000 2000
2000 2000
2000 2000
2000 2000
2000 2000
2000 2000
2000 2000
2000 2000 jelly
1000 1100
350 700
200 800
2000 2000
2000 432
2000 2000
2000 2000
2000 2000
2000 2000
20 2000
2000 2000
350 35
200 800
2000 2000
2000 2000
2000 2000
2000 2000
2000 2000
2000 2000
2000 2000
2000 2000
2000 2000
2000 2000
2000 2000
15 2000
2000 2000
样例输出
900
105
提示
来源
————————————————————————————————————————
思路:分析可知一定是先删去前面和后面然后一端添加字符,所以先n^2处理出前后删减的花费,然后用dp数字达标维护,用dp[i][j][0]表示区间[i,j]向前扩展成回文的最小花费,用dp[i][j][1]表示区间[i,j]向后扩展成回文的最小花费
#include <iostream>
#include<queue>
#include<cstdio>
#include<algorithm>
#include<cmath>
#include<set>
#include<cstring>
using namespace std;
#define LL long long int dp[1005][1005][2];
int a[30],b[30];
char s[1005];
int L[1005],R[1005];
bool dd[1005][1005]; int main()
{
while(~scanf("%s",s))
{ for(int i=0; i<26; i++)
scanf("%d%d",&a[i],&b[i]);
int n=strlen(s);
memset(dd,0,sizeof dd);
for(int i=1; i<=n; i++)
{
dd[i][i]=true;
}
for(int i=1; i<n; i++)
{
if(s[i-1]==s[i])
dd[i][i+1]=true;
}
for(int j=2; j<n; j++)
for(int i=1; i<=n; i++)
{
if(i+j>n)
break;
dd[i][i+j]=s[i-1]==s[i+j-1]&dd[i+1][i+j-1];
} for(int i=0; i<n; i++)
dp[i][i][0]=0,dp[i][i][1]=0;
for(int j=1; j<n; j++)
{
for(int i=1; i<=n; i++)
{
if(i+j>n) break; if(dd[i][i+j])
{
dp[i][i+j][0]= dp[i][i+j][1]=0;
}
else
{
dp[i][i+j][0]=dp[i][i+j-1][0]+b[s[i+j-1]-'a'];
dp[i][i+j][1]=dp[i+1][i+j][1]+b[s[i-1]-'a'];
} }
}
L[0]=0;
L[1]=a[s[0]-'a'];
for(int i=2; i<=n; i++)
{
L[i]=L[i-1]+a[s[i-1]-'a'];
}
R[n+1]=0;
R[n]=a[s[n-1]-'a'];
for(int i=n-1; i>0; i--)
{
R[i]=R[i+1]+a[s[i-1]-'a'];
} int mn=0x3f3f3f3f;
for(int i=1; i<=n; i++)
{
for(int j=n; j>=i; j--)
{
mn=min(mn,L[i-1]+R[j+1]+min(dp[i][j][0],dp[i][j][1]));
}
}
printf("%d\n",mn); } return 0;
}