• [USACO07OPEN]便宜的回文题解


    欢迎来看看呀

    题目链接

    一道十分巧妙的区间DP题

    首先我们必须要发现一个重要的性质,不然状态转移方程会十分的复杂,那么就是删除一个字符和增加一个字符的效果是等价的

    举个栗子,我们现在有一个字符串abccbdpl,要将a[bccbd]pl括起来的一段字符变成回文

    变成[dbccbd]和[bccb]对后面所造成的影响是一样的,所以增加或删除一个字符(i)的最小代价(cost[i])变为(min(add[i],del[i]))

    然后便可以只考虑添加字符的情况,(dp[i][j])表示将位置为(i)(j)的字符变成回文串的代价,枚举i和j

    如果此时的(s[i])=(s[j]),(dp[i][j]=min(dp[i][j],dp[i+1][j-1]))

    (s[i]!=s[j]),(dp[i][j]=min(dp[i][j-1]+cost[j],dp[i+1][j]+cost[i]))

    还要注意一下边界问题,(dp[i][i]=0,dp[i][i-1]=0),其他的都要初始化为极大值

    代码

    #include<iostream>
    #include<cstdio>
    using namespace std;
    int n,m,mp[400],f[2003][2003],a,b,r;
    char a1[2003],p;
    int main()
    {
    	scanf("%d%d%s",&n,&m,&a1);
    	for(int i=1; i<=n; i++)
    	{
    		cin>>p;
    		scanf("%d%d",&a,&b);
    		mp[p]=min(a,b);
    	}
    	for(int i=0; i<m; i++)
    		for(int j=i+1; j<m; j++)
    			f[i][j]=1e9;
    	for(int i=1; i<m; i++)
    	{
    		for(int j=0; j+i<m; j++)
    		{
    			r=j+i;
    			f[j][r]=min(f[j+1][r]+mp[a1[j]],f[j][r-1]+mp[a1[r]]);
    			if(a1[j]==a1[r])
    			f[j][r]=min(f[j][r],f[j+1][r-1]);
    		}
    	}
    	cout<<f[0][m-1];
    	return 0;
    }
    
  • 相关阅读:
    网站链接
    CSS 初始化
    常见浏览器+浏览器内核
    sublime及其插件的安装
    数码时钟.js
    每天迁移MySQL历史数据到历史库Python脚本
    python和redis简单交互
    python和mongodb简单交互
    python3与mysql交互
    Red Hat Enterprise Linux 7.2修改主机名(hostname)
  • 原文地址:https://www.cnblogs.com/dzice/p/12000179.html
Copyright © 2020-2023  润新知