poj 3280 Cheapest Palindrome——DP
先开始想了个错的……唉现在思维还进化地不足啊……
首先要发现的是添加和删除是一样的,所以我们在选cost的时候只用选delete和add的较小值就可以了。
状态转移方程:
if(st[i]==st[j])
dp[i][j]=dp[i+1][j-1];
else if(st[i]!=st[j])
dp[i][j]=max(dp[i+1][j]+cost[st[i]-'a'],dp[i][j-1]+cost[st[j]-'a']);
在用记忆化搜索解决。注意边界情况,否则会搜死。
//time:157MS
//memory:16260K
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<algorithm>
#include<cmath>
int dp[2005][2010];
int cost[30];
char st[2010];
int min(int a,int b)
{
return a>b?b:a;
}
int DP(int i,int j)
{
if(i==j)
return dp[i][j]=0;
if(dp[i][j]>=0)
return dp[i][j];
if(st[i]==st[j])
{
if(i+1==j)
return dp[i][j]=0;//这个地方在编译的时候没写,就搜死了……
return dp[i][j]=DP(i+1,j-1);
}
else
{
return dp[i][j]=min(DP(i+1,j)+cost[st[i]-'a'],DP(i,j-1)+cost[st[j]-'a']);
}
}
int main(void)
{
int n,m;
while(scanf("%d %d",&n,&m)==2)
{
memset(dp,-1,sizeof(dp));
memset(cost,0,sizeof(cost));
memset(st,0,sizeof(st));
if(!m)
{
puts("0");
continue;
}
scanf("%s",st+1);
int i;
for(i=1;i<=n;i++)
{
char s[10];
int a,b;
scanf("%s %d %d",s,&a,&b);
cost[s[0]-'a']=min(a,b);
}
printf("%d\n",DP(1,m));
}
}