poj3280 2010.4.14

来源:互联网 发布:软件技术开发合同 编辑:程序博客网 时间:2024/06/04 18:21

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;}


0 0
原创粉丝点击