zoukankan      html  css  js  c++  java
  • POJ 3280 Cheapest Palindrome 【区间DP】

    题目链接

    题意

    给你一串字符串,并给出添加以及删除(在任意位置)每种字符的花费,问把这个字符串变成回文串所需的最少花费


    分析

    经典的区间DP

    状态


    dp[i][j]Si,j1

    习惯设成前闭后开区间

    状态转移方程

    如果当前子串最前面和最后面的字符本来就相同,当前的最小花费就等于里面的子串的最小花费。而若不相等,则考虑在前后加上或删去与两边相同的字符。

    if(k<=1)
        dp[i][i+k]=0;
    else if(org[i]==org[i+k-1])
        dp[i][i+k]=dp[i+1][i+k-1];
    else
    {
        dp[i][i+k]=min(dp[i][i+k],dp[i+1][i+k]+cost[org[i]-'a'][1]);
        dp[i][i+k]=min(dp[i][i+k],dp[i+1][i+k]+cost[org[i]-'a'][0]);
        dp[i][i+k]=min(dp[i][i+k],dp[i][i+k-1]+cost[org[i+k-1]-'a'][1]);
        dp[i][i+k]=min(dp[i][i+k],dp[i][i+k-1]+cost[org[i+k-1]-'a'][0]);
    }

    初始化、递推顺序、最终解

    把dp全部初始化为正无穷,也可以顺便把空串和长度为1的情况初始化为0
    从转移方程中可以看出,一个状态总是依赖于一些比它短的区间的状态,所以dp中循环的顺序应当按串的长度为依据来递推。
    最终解就是dp[0][m]


    AC代码

    //POJ 3280 Cheapest Palindrome
    //AC 2016-8-2 21:36:55
    //DP
    #include <iostream>
    #include <cstdio>
    #include <algorithm>
    #include <cmath>
    #include <cctype>
    #include <cstdlib>
    #include <cstring>
    #include <vector>
    #include <set>
    #include <string>
    #include <map>
    #include <queue>
    #include <deque>
    #include <list>
    #include <sstream>
    #include <stack>
    using namespace std;
    
    #define cls(x) memset(x,0,sizeof x)
    #define inf(x) memset(x,0x3f,sizeof x)
    #define neg(x) memset(x,-1,sizeof x)
    #define ninf(x) memset(x,0xc0,sizeof x)
    #define st0(x) memset(x,false,sizeof x)
    #define st1(x) memset(x,true,sizeof x)
    #define INF 0x3f3f3f3f
    #define lowbit(x) x&(-x)
    #define bug cout<<"here"<<endl;
    //#define debug
    
    int N,M;
    int cost[30][2];
    int dp[3000][3000];
    char org[3000];
    
    int main()
    {
        #ifdef debug
            freopen("E:\Documents\code\input.txt","r",stdin);
            freopen("E:\Documents\code\output.txt","w",stdout);
        #endif
        while(cin>>N>>M)
        {
            cin>>org;
            inf(cost);
            inf(dp);
            char c;int a,b;
            for(int i=0;i<N;++i)
            {
                cin>>c;
                cin>>cost[c-'a'][0]>>cost[c-'a'][1];
            }
            for(int k=0;k<=M;++k)
            {
                for(int i=0;i<=M-k;++i)
                {
                    if(k<=1)
                        dp[i][i+k]=0;
                    else if(org[i]==org[i+k-1])
                        dp[i][i+k]=dp[i+1][i+k-1];
                    else
                    {
                        dp[i][i+k]=min(dp[i][i+k],dp[i+1][i+k]+cost[org[i]-'a'][1]);
                        dp[i][i+k]=min(dp[i][i+k],dp[i+1][i+k]+cost[org[i]-'a'][0]);
                        dp[i][i+k]=min(dp[i][i+k],dp[i][i+k-1]+cost[org[i+k-1]-'a'][1]);
                        dp[i][i+k]=min(dp[i][i+k],dp[i][i+k-1]+cost[org[i+k-1]-'a'][0]);
                    }
                }
            }
            cout<<dp[0][M]<<endl;
        }
        return 0;
    }
    
  • 相关阅读:
    Java实现 蓝桥杯VIP 算法训练 字符串逆序
    Java实现 蓝桥杯VIP 算法训练 字符串逆序
    Java实现 蓝桥杯VIP 算法训练 最长字符串
    Java实现 蓝桥杯VIP 算法训练 最长字符串
    Java实现 蓝桥杯VIP 算法训练 最长字符串
    Java实现 蓝桥杯VIP 算法训练 最长字符串
    Java实现 蓝桥杯VIP 算法训练 最长字符串
    Java实现 蓝桥杯VIP 算法训练 成绩的等级输出
    Java实现 蓝桥杯VIP 算法训练 成绩的等级输出
    Qt 自定义model实现文件系统的文件名排序
  • 原文地址:https://www.cnblogs.com/DrCarlluo/p/6580598.html
Copyright © 2011-2022 走看看