poj3280 2010.4.14
状态 memo[i][j] 表示从开始到第 i 个字符和从第 j 个字符到结尾两个字符串匹配需要的最小耗费。
状态转移可能有三种情况:
1. memo[i - 1][j] + cost[i]
2. memo[i][j + 1] + cost[j]
3. memo[i - 1][j + 1] (if str[i] == str[j])
注意:
1.只要保存单个字符删除或添加两者的最小值即可。
2.最终方案可能有一个中间字符,然后两边匹配,也可能没有中间字符,此时j = i + 1。
#include <cstdio>
#include <cstring>
#define MAXN 26
#define MAXM 2000
#define INT_MAX 2147483647
#define max(a,b) (((a)>(b))?(a):(b))
#define min(a,b) (((a)<(b))?(a):(b))
int m,n;
int mEnd;
int memo[MAXM+1][MAXM+2];
int ls[MAXN];
char str[MAXM+2];
void init()
{
int i;
scanf("%d%d%s",&n,&m,str+1);
mEnd=m+1;
for(i=1;i<=m;i++)
{
str[i]-='a';
}
char c[2];
int a,d;
for(i=0;i<n;i++)
{
scanf("%s%d%d",c,&a,&d);
ls[c[0]-'a']=min(a,d);
}
}
int dpit()
{
int res=INT_MAX;
int i,j;
int minSum[MAXM+1];
minSum[0]=0;
int sum=0;
for(i=1;i<=m;i++)
{
sum+=ls[str[i]];
minSum[i]=sum;
}
for(i=0;i<=m;i++)
{
memo[i][mEnd]=minSum[i];
memo[0][i+1]=minSum[m]-minSum[i];
}
int iEnd=m;
int op,minOp;
for(i=1;i<iEnd;i++)
{
for(j=m;j>i;j--)
{
op=memo[i-1][j]+ls[str[i]];
minOp=op;
op=memo[i][j+1]+ls[str[j]];
minOp=min(minOp,op);
if(str[i]==str[j])
{
op=memo[i-1][j+1];
minOp=min(minOp,op);
}
memo[i][j]=minOp;
}
}
for(i=0;i<m;i++)
{
if (memo[i][i+1]<res)
{
res=memo[i][i+1];
}
if(memo[i][i+2]<res)
{
res=memo[i][i+2];
}
}
if(memo[m][mEnd]<res)
{
res=memo[m][mEnd];
}
return res;
}
int main()
{
memset(memo,0,sizeof(memo));
init();
printf("%d\n",dpit());
return 0;
}
本文详细介绍了如何使用动态规划解决POJ3280问题,通过状态转移方程和初始化策略,实现了高效的算法求解过程。文章包括问题背景、解题思路、代码实现及时间复杂度分析。

1483

被折叠的 条评论
为什么被折叠?



