poj3280 2010.4.14

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




评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值