• [poj3280]Cheapest Palindrome_区间dp


    Cheapest Palindrome poj-3280

        题目大意:给出一个字符串,以及每种字符的加入代价和删除代价,求将这个字符串通过删减元素变成回文字符串的最小代价。

        注释:每种字符都是小写英文字符,1<=代价cost<=1000,字符串长度<=2000.

          想法:通过之前两道区间dp的铺垫,对区间dp有了一个大概的了解,但是这道题无疑是一道比较特别的区间dp。

            首先,我们设dp状态,这显然是容易的:ans[i][j]表示将原字符串从i到j变成回文串的最小代价。

            之后,我们考虑转移方程:对于一个字符串,我们显然不可以想之前的dp一样枚举端点,一是回文串并不满足两个回文串捏一起还是回文串的性质;二是枚举断点的时间复杂度是$O(n^3)$的,我们并不能承受。考虑其他的转移方式,通过回文串的性质,我们可以很清楚的明白——只有通过这个字符串的中间进行转移才是可行的。我们想到:

            分两种情况:

            1.s[i]==s[j]这时ans[i][j]=ans[i+1][j-1](此处注意,当这个字符串长度是2时,ans[i][j]=0)

            2.s[i]!=s[j],这时我们可以通过对于端点元素的增减来达到以第一种情况

              ans[i][j]=min(ans[i][j],min(ans[i][j]+min(val[s[j]-'0'],del[s[j]-'0']),ans[i+1][j]+min(val[s[i]-'0'],del[s[i]-'0'])));

          最后,附上丑陋的代码... ...

    #include <iostream>
    #include <cstdio>
    #include <cstring>
    using namespace std;
    char s[2010];
    int ans[2010][2010];
    int val[200];
    int del[220];
    char a[10];
    int v,d;
    int main()
    {
    	int n,m;
    	scanf("%d%d",&n,&m);
    	scanf("%s",s+1);
    	for(int i=1;i<=n;i++)
    	{
    		scanf("%s%d%d",a+1,&v,&d);
    		int middle=a[1]-'0';
    		val[middle]=v;del[middle]=d;
    	}
    	memset(ans,0x3f,sizeof(ans));
    	for(int i=1;i<=m;i++)
    	{
    		ans[i][i]=0;
    	}
    	for(int len=2;len<=m;len++)
    	{
    		for(int i=1;i<=m;i++)
    		{
    			if(i+len-1>m) break;
    			if(s[i]==s[i+len-1])
    			{
    				if(len==2) ans[i][i+len-1]=0;
    				ans[i][i+len-1]=min(ans[i][i+len-1],ans[i+1][i+len-2]);
    			}
    			ans[i][i+len-1]=min(ans[i][i+len-1],
    				min(ans[i][i+len-2]+min(val[s[i+len-1]-'0'],del[s[i+len-1]-'0']),
    					ans[i+1][i+len-1]+min(val[s[i]-'0'],del[s[i]-'0'])));
    		}
    	}
    	printf("%d
    ",ans[1][m]);
    	return 0;
    }
    

         小结:这个题于端点的处理是很细腻的。

          在写这个恐怖的转移方程时注意换行,在逗号和分号都是可以换行的。

          len==2时需要特判qwq

  • 相关阅读:
    javascript--运算符
    线程池 的创建小列子,以及参数的介绍
    @SpringBootApplication注解
    SpringBoot 基础知识学习(二)——配置文件多环境配置
    springboot 配置文件读取的两种方式,以及使用到的注解解释
    用虚拟机安装了一台Linux系统,突然想克隆一台服务器,克隆后发现无法上网,如何解决?
    ---oracle 数据库的设计,PL/SQL(loop,for,if,case,while)
    xml的解析技术, 它们之间的区别?
    -----oracle优化之表分区
    --------oracle 的伪表和伪劣,简单的分页
  • 原文地址:https://www.cnblogs.com/ShuraK/p/8520582.html
Copyright © 2020-2023  润新知